Merge pull request #1770 from jedevc/integration-tests
commit
c59fc18325
@ -0,0 +1,81 @@
|
||||
name: test
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'v[0-9]*'
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '.github/releases.json'
|
||||
- 'README.md'
|
||||
- 'docs/**'
|
||||
|
||||
env:
|
||||
SETUP_BUILDX_VERSION: "latest"
|
||||
SETUP_BUILDKIT_IMAGE: "moby/buildkit:latest"
|
||||
TESTFLAGS: "-v --parallel=6 --timeout=30m"
|
||||
TESTFLAGS_DOCKER: "-v --parallel=1 --timeout=30m"
|
||||
GOTESTSUM_FORMAT: "standard-verbose"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
worker:
|
||||
- docker
|
||||
- docker-container
|
||||
- remote
|
||||
pkg:
|
||||
- ./tests
|
||||
typ:
|
||||
- integration
|
||||
# already run as part of build.yml
|
||||
# include:
|
||||
# - pkg: ./...
|
||||
# skip-integration-tests: 1
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Expose GitHub Runtime
|
||||
uses: crazy-max/ghaction-github-runtime@v2
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
version: ${{ env.SETUP_BUILDX_VERSION }}
|
||||
driver-opts: image=${{ env.SETUP_BUILDKIT_IMAGE }}
|
||||
buildkitd-flags: --debug
|
||||
-
|
||||
name: Test
|
||||
run: |
|
||||
export TEST_REPORT_SUFFIX=-${{ github.job }}-$(echo "${{ matrix.pkg }}-${{ matrix.skip-integration-tests }}-${{ matrix.worker }}" | tr -dc '[:alnum:]-\n\r' | tr '[:upper:]' '[:lower:]')
|
||||
./hack/test ${{ matrix.typ }}
|
||||
env:
|
||||
TEST_DOCKERD: "${{ (matrix.worker == 'docker' || matrix.worker == 'docker-container') && '1' || '0' }}"
|
||||
TESTFLAGS: "${{ (matrix.worker == 'docker' || matrix.worker == 'docker-container') && env.TESTFLAGS_DOCKER || env.TESTFLAGS }} --run=//worker=${{ matrix.worker }}$"
|
||||
TESTPKGS: "${{ matrix.pkg }}"
|
||||
SKIP_INTEGRATION_TESTS: "${{ matrix.skip-integration-tests }}"
|
||||
-
|
||||
name: Generate annotations
|
||||
if: always()
|
||||
uses: crazy-max/.github/.github/actions/gotest-annotations@1a64ea6d01db9a48aa61954cb20e265782c167d9
|
||||
with:
|
||||
directory: ./bin/testreports
|
||||
-
|
||||
name: Upload test reports
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: test-reports
|
||||
path: ./bin/testreports
|
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
: "${BUILDX_CMD=docker buildx}"
|
||||
: "${CACHE_FROM=}"
|
||||
: "${CACHE_TO=}"
|
||||
|
||||
: ${TEST_INTEGRATION=}
|
||||
: ${TEST_REPORT_SUFFIX=}
|
||||
: ${TEST_KEEP_CACHE=}
|
||||
: ${TEST_DOCKERD=}
|
||||
: ${TEST_BUILDKIT_IMAGE=}
|
||||
|
||||
if [ -n "$CACHE_FROM" ]; then
|
||||
for cfrom in $CACHE_FROM; do
|
||||
setFlags+=(--set "*.cache-from=$cfrom")
|
||||
done
|
||||
fi
|
||||
if [ -n "$CACHE_TO" ]; then
|
||||
for cto in $CACHE_TO; do
|
||||
setFlags+=(--set "*.cache-to=$cto")
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$#" == 0 ]; then TEST_INTEGRATION=1; fi
|
||||
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
integration)
|
||||
TEST_INTEGRATION=1
|
||||
;;
|
||||
*)
|
||||
echo "unknown arg $1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
iid="buildx-tests"
|
||||
|
||||
testReportsDir="$(pwd)/bin/testreports"
|
||||
mkdir -p "$testReportsDir"
|
||||
testReportsVol="-v $testReportsDir:/testreports"
|
||||
gotestsumArgs="--format=standard-verbose --jsonfile=/testreports/go-test-report$TEST_REPORT_SUFFIX.json --junitfile=/testreports/junit-report$TEST_REPORT_SUFFIX.xml"
|
||||
gotestArgs="-mod=vendor -coverprofile=/testreports/coverage-report$TEST_REPORT_SUFFIX.txt -covermode=atomic"
|
||||
|
||||
${BUILDX_CMD} bake integration-test "${setFlags[@]}" --set "*.output=type=docker,name=$iid"
|
||||
|
||||
cacheVolume="buildx-test-cache"
|
||||
if ! docker container inspect "$cacheVolume" >/dev/null 2>/dev/null; then
|
||||
docker create -v /root/.cache -v /root/.cache/registry -v /go/pkg/mod --name "$cacheVolume" alpine
|
||||
fi
|
||||
|
||||
if [ "$TEST_INTEGRATION" == 1 ]; then
|
||||
cid=$(docker create --rm -v /tmp $testReportsVol --volumes-from=$cacheVolume -e GITHUB_REF -e TEST_DOCKERD -e TEST_BUILDKIT_IMAGE -e SKIP_INTEGRATION_TESTS -e GOTESTSUM_FORMAT ${BUILDKIT_INTEGRATION_SNAPSHOTTER:+"-eBUILDKIT_INTEGRATION_SNAPSHOTTER"} -e BUILDKIT_REGISTRY_MIRROR_DIR=/root/.cache/registry --privileged $iid gotestsum $gotestsumArgs --packages="${TESTPKGS:-./...}" -- $gotestArgs ${TESTFLAGS:--v})
|
||||
docker start -a -i $cid
|
||||
fi
|
||||
|
||||
if [ "$TEST_KEEP_CACHE" != "1" ]; then
|
||||
docker rm -v $cacheVolume
|
||||
fi
|
@ -0,0 +1,102 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/continuity/fs/fstest"
|
||||
"github.com/moby/buildkit/util/contentutil"
|
||||
"github.com/moby/buildkit/util/testutil"
|
||||
"github.com/moby/buildkit/util/testutil/integration"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func buildCmd(sb integration.Sandbox, args ...string) (string, error) {
|
||||
args = append([]string{"build", "--progress=quiet"}, args...)
|
||||
cmd := buildxCmd(sb, args...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
return string(out), err
|
||||
}
|
||||
|
||||
var buildTests = []func(t *testing.T, sb integration.Sandbox){
|
||||
testBuild,
|
||||
testBuildLocalExport,
|
||||
testBuildRegistryExport,
|
||||
testBuildTarExport,
|
||||
}
|
||||
|
||||
func testBuild(t *testing.T, sb integration.Sandbox) {
|
||||
dir := createTestProject(t)
|
||||
out, err := buildCmd(sb, dir)
|
||||
require.NoError(t, err, string(out))
|
||||
}
|
||||
|
||||
func testBuildLocalExport(t *testing.T, sb integration.Sandbox) {
|
||||
dir := createTestProject(t)
|
||||
out, err := buildCmd(sb, fmt.Sprintf("--output=type=local,dest=%s/result", dir), dir)
|
||||
require.NoError(t, err, string(out))
|
||||
|
||||
dt, err := os.ReadFile(dir + "/result/bar")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "foo", string(dt))
|
||||
}
|
||||
|
||||
func testBuildTarExport(t *testing.T, sb integration.Sandbox) {
|
||||
dir := createTestProject(t)
|
||||
out, err := buildCmd(sb, fmt.Sprintf("--output=type=tar,dest=%s/result.tar", dir), dir)
|
||||
require.NoError(t, err, string(out))
|
||||
|
||||
dt, err := os.ReadFile(fmt.Sprintf("%s/result.tar", dir))
|
||||
require.NoError(t, err)
|
||||
m, err := testutil.ReadTarToMap(dt, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Contains(t, m, "bar")
|
||||
require.Equal(t, "foo", string(m["bar"].Data))
|
||||
}
|
||||
|
||||
func testBuildRegistryExport(t *testing.T, sb integration.Sandbox) {
|
||||
dir := createTestProject(t)
|
||||
|
||||
registry, err := sb.NewRegistry()
|
||||
if errors.Is(err, integration.ErrRequirements) {
|
||||
t.Skip(err.Error())
|
||||
}
|
||||
require.NoError(t, err)
|
||||
target := registry + "/buildx/registry:latest"
|
||||
|
||||
out, err := buildCmd(sb, fmt.Sprintf("--output=type=image,name=%s,push=true", target), dir)
|
||||
require.NoError(t, err, string(out))
|
||||
|
||||
desc, provider, err := contentutil.ProviderFromRef(target)
|
||||
require.NoError(t, err)
|
||||
imgs, err := testutil.ReadImages(sb.Context(), provider, desc)
|
||||
require.NoError(t, err)
|
||||
|
||||
pk := platforms.Format(platforms.Normalize(platforms.DefaultSpec()))
|
||||
img := imgs.Find(pk)
|
||||
require.NotNil(t, img)
|
||||
require.Len(t, img.Layers, 1)
|
||||
require.Equal(t, img.Layers[0]["bar"].Data, []byte("foo"))
|
||||
}
|
||||
|
||||
func createTestProject(t *testing.T) string {
|
||||
dockerfile := []byte(`
|
||||
FROM busybox:latest AS base
|
||||
COPY foo /etc/foo
|
||||
RUN cp /etc/foo /etc/bar
|
||||
|
||||
FROM scratch
|
||||
COPY --from=base /etc/bar /bar
|
||||
`)
|
||||
dir, err := tmpdir(
|
||||
t,
|
||||
fstest.CreateFile("Dockerfile", dockerfile, 0600),
|
||||
fstest.CreateFile("foo", []byte("foo"), 0600),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
return dir
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/moby/buildkit/util/testutil/integration"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func inspectCmd(sb integration.Sandbox, args ...string) (string, error) {
|
||||
args = append([]string{"inspect"}, args...)
|
||||
cmd := buildxCmd(sb, args...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
return string(out), err
|
||||
}
|
||||
|
||||
var inspectTests = []func(t *testing.T, sb integration.Sandbox){
|
||||
testInspect,
|
||||
}
|
||||
|
||||
func testInspect(t *testing.T, sb integration.Sandbox) {
|
||||
out, err := inspectCmd(sb)
|
||||
require.NoError(t, err, string(out))
|
||||
|
||||
var name string
|
||||
var driver string
|
||||
for _, line := range strings.Split(out, "\n") {
|
||||
if v, ok := strings.CutPrefix(line, "Name:"); ok && name == "" {
|
||||
name = strings.TrimSpace(v)
|
||||
}
|
||||
if v, ok := strings.CutPrefix(line, "Driver:"); ok && driver == "" {
|
||||
driver = strings.TrimSpace(v)
|
||||
}
|
||||
}
|
||||
require.Equal(t, sb.Address(), name)
|
||||
require.Equal(t, sb.Name(), driver)
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
|
||||
"github.com/containerd/continuity/fs/fstest"
|
||||
"github.com/moby/buildkit/util/testutil/integration"
|
||||
)
|
||||
|
||||
func tmpdir(t *testing.T, appliers ...fstest.Applier) (string, error) {
|
||||
tmpdir := t.TempDir()
|
||||
if err := fstest.Apply(appliers...).Apply(tmpdir); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return tmpdir, nil
|
||||
}
|
||||
|
||||
func buildxCmd(sb integration.Sandbox, args ...string) *exec.Cmd {
|
||||
if builder := sb.Address(); builder != "" {
|
||||
args = append([]string{"--builder=" + builder}, args...)
|
||||
}
|
||||
cmd := exec.Command("buildx", args...)
|
||||
if context := sb.DockerAddress(); context != "" {
|
||||
cmd.Env = append(os.Environ(), "DOCKER_CONTEXT="+context)
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/distribution/distribution/v3/reference"
|
||||
"github.com/docker/buildx/tests/workers"
|
||||
"github.com/moby/buildkit/util/testutil/integration"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if integration.IsTestDockerd() {
|
||||
workers.InitDockerWorker()
|
||||
workers.InitDockerContainerWorker()
|
||||
} else {
|
||||
workers.InitRemoteWorker()
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegration(t *testing.T) {
|
||||
var tests []func(t *testing.T, sb integration.Sandbox)
|
||||
tests = append(tests, buildTests...)
|
||||
tests = append(tests, inspectTests...)
|
||||
tests = append(tests, lsTests...)
|
||||
testIntegration(t, tests...)
|
||||
}
|
||||
|
||||
func testIntegration(t *testing.T, funcs ...func(t *testing.T, sb integration.Sandbox)) {
|
||||
mirroredImages := integration.OfficialImages("busybox:latest", "alpine:latest")
|
||||
buildkitImage := "docker.io/moby/buildkit:buildx-stable-1"
|
||||
if integration.IsTestDockerd() {
|
||||
if img, ok := os.LookupEnv("TEST_BUILDKIT_IMAGE"); ok {
|
||||
ref, err := reference.ParseNormalizedNamed(img)
|
||||
if err == nil {
|
||||
buildkitImage = ref.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
mirroredImages["moby/buildkit:buildx-stable-1"] = buildkitImage
|
||||
mirrors := integration.WithMirroredImages(mirroredImages)
|
||||
|
||||
tests := integration.TestFuncs(funcs...)
|
||||
integration.Run(t, tests, mirrors)
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/moby/buildkit/util/testutil/integration"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func lsCmd(sb integration.Sandbox, args ...string) (string, error) {
|
||||
args = append([]string{"ls"}, args...)
|
||||
cmd := buildxCmd(sb, args...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
return string(out), err
|
||||
}
|
||||
|
||||
var lsTests = []func(t *testing.T, sb integration.Sandbox){
|
||||
testLs,
|
||||
}
|
||||
|
||||
func testLs(t *testing.T, sb integration.Sandbox) {
|
||||
out, err := lsCmd(sb)
|
||||
require.NoError(t, err, string(out))
|
||||
|
||||
for _, line := range strings.Split(out, "\n") {
|
||||
if strings.Contains(line, sb.Address()) {
|
||||
require.Contains(t, line, sb.Name())
|
||||
return
|
||||
}
|
||||
}
|
||||
require.Fail(t, out)
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package workers
|
||||
|
||||
type backend struct {
|
||||
builder string
|
||||
context string
|
||||
}
|
||||
|
||||
func (s *backend) Address() string {
|
||||
return s.builder
|
||||
}
|
||||
|
||||
func (s *backend) DockerAddress() string {
|
||||
return s.context
|
||||
}
|
||||
|
||||
func (s *backend) ContainerdAddress() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *backend) Snapshotter() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *backend) Rootless() bool {
|
||||
return false
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package workers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/moby/buildkit/identity"
|
||||
"github.com/moby/buildkit/util/testutil/integration"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func InitDockerContainerWorker() {
|
||||
integration.Register(&containerWorker{
|
||||
id: "docker-container",
|
||||
})
|
||||
}
|
||||
|
||||
type containerWorker struct {
|
||||
id string
|
||||
}
|
||||
|
||||
func (w *containerWorker) Name() string {
|
||||
return w.id
|
||||
}
|
||||
|
||||
func (w *containerWorker) Rootless() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *containerWorker) New(ctx context.Context, cfg *integration.BackendConfig) (integration.Backend, func() error, error) {
|
||||
bk, bkclose, err := dockerWorker{id: w.id}.New(ctx, cfg)
|
||||
if err != nil {
|
||||
return bk, bkclose, err
|
||||
}
|
||||
|
||||
name := "integration-container-" + identity.NewID()
|
||||
cmd := exec.Command("buildx", "create",
|
||||
"--bootstrap",
|
||||
"--name="+name,
|
||||
"--config="+cfg.ConfigFile,
|
||||
"--driver=docker-container",
|
||||
"--driver-opt=network=host",
|
||||
)
|
||||
cmd.Env = append(os.Environ(), "DOCKER_CONTEXT="+bk.DockerAddress())
|
||||
if err := cmd.Run(); err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "failed to create buildx instance %s", name)
|
||||
}
|
||||
|
||||
cl := func() error {
|
||||
var err error
|
||||
if err1 := bkclose(); err == nil {
|
||||
err = err1
|
||||
}
|
||||
cmd := exec.Command("buildx", "rm", "-f", name)
|
||||
if err1 := cmd.Run(); err == nil {
|
||||
err = err1
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return &backend{
|
||||
context: bk.DockerAddress(),
|
||||
builder: name,
|
||||
}, cl, nil
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package workers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
|
||||
"github.com/moby/buildkit/identity"
|
||||
"github.com/moby/buildkit/util/testutil/integration"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func InitDockerWorker() {
|
||||
integration.Register(&dockerWorker{
|
||||
id: "docker",
|
||||
})
|
||||
}
|
||||
|
||||
type dockerWorker struct {
|
||||
id string
|
||||
}
|
||||
|
||||
func (c dockerWorker) Name() string {
|
||||
return c.id
|
||||
}
|
||||
|
||||
func (c dockerWorker) Rootless() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c dockerWorker) New(ctx context.Context, cfg *integration.BackendConfig) (b integration.Backend, cl func() error, err error) {
|
||||
moby := integration.Moby{
|
||||
ID: c.id,
|
||||
}
|
||||
bk, bkclose, err := moby.New(ctx, cfg)
|
||||
if err != nil {
|
||||
return bk, cl, err
|
||||
}
|
||||
|
||||
name := "integration-" + identity.NewID()
|
||||
cmd := exec.Command("docker", "context", "create",
|
||||
name,
|
||||
"--docker", "host="+bk.DockerAddress(),
|
||||
)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return nil, cl, errors.Wrapf(err, "failed to create buildx instance %s", name)
|
||||
}
|
||||
|
||||
cl = func() error {
|
||||
var err error
|
||||
if err1 := bkclose(); err == nil {
|
||||
err = err1
|
||||
}
|
||||
cmd := exec.Command("docker", "context", "rm", "-f", name)
|
||||
if err1 := cmd.Run(); err1 != nil {
|
||||
err = errors.Wrapf(err1, "failed to remove buildx instance %s", name)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return &backend{
|
||||
builder: name,
|
||||
context: name,
|
||||
}, cl, nil
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package workers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
|
||||
"github.com/moby/buildkit/identity"
|
||||
"github.com/moby/buildkit/util/testutil/integration"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func InitRemoteWorker() {
|
||||
integration.Register(&remoteWorker{
|
||||
id: "remote",
|
||||
})
|
||||
}
|
||||
|
||||
type remoteWorker struct {
|
||||
id string
|
||||
}
|
||||
|
||||
func (w remoteWorker) Name() string {
|
||||
return w.id
|
||||
}
|
||||
|
||||
func (w remoteWorker) Rootless() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (w remoteWorker) New(ctx context.Context, cfg *integration.BackendConfig) (b integration.Backend, cl func() error, err error) {
|
||||
oci := integration.OCI{ID: w.id}
|
||||
bk, bkclose, err := oci.New(ctx, cfg)
|
||||
if err != nil {
|
||||
return bk, cl, err
|
||||
}
|
||||
|
||||
name := "integration-remote-" + identity.NewID()
|
||||
cmd := exec.Command("buildx", "create",
|
||||
"--bootstrap",
|
||||
"--name="+name,
|
||||
"--driver=remote",
|
||||
bk.Address(),
|
||||
)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "failed to create buildx instance %s", name)
|
||||
}
|
||||
|
||||
cl = func() error {
|
||||
var err error
|
||||
if err1 := bkclose(); err == nil {
|
||||
err = err1
|
||||
}
|
||||
cmd := exec.Command("buildx", "rm", "-f", name)
|
||||
if err1 := cmd.Run(); err == nil {
|
||||
err = err1
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return &backend{
|
||||
builder: name,
|
||||
}, cl, nil
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
## Code of Conduct
|
||||
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
|
||||
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
|
||||
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
|
||||
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
|
||||
opensource-codeofconduct@amazon.com with any additional questions or comments.
|
||||
|
@ -1,3 +1,3 @@
|
||||
AWS SDK for Go
|
||||
Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
Copyright 2014-2015 Stripe, Inc.
|
||||
|
@ -0,0 +1,122 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials/ssocreds"
|
||||
"github.com/aws/aws-sdk-go-v2/service/ssooidc"
|
||||
smithybearer "github.com/aws/smithy-go/auth/bearer"
|
||||
)
|
||||
|
||||
// resolveBearerAuthToken extracts a token provider from the config sources.
|
||||
//
|
||||
// If an explicit bearer authentication token provider is not found the
|
||||
// resolver will fallback to resolving token provider via other config sources
|
||||
// such as SharedConfig.
|
||||
func resolveBearerAuthToken(ctx context.Context, cfg *aws.Config, configs configs) error {
|
||||
found, err := resolveBearerAuthTokenProvider(ctx, cfg, configs)
|
||||
if found || err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resolveBearerAuthTokenProviderChain(ctx, cfg, configs)
|
||||
}
|
||||
|
||||
// resolveBearerAuthTokenProvider extracts the first instance of
|
||||
// BearerAuthTokenProvider from the config sources.
|
||||
//
|
||||
// The resolved BearerAuthTokenProvider will be wrapped in a cache to ensure
|
||||
// the Token is only refreshed when needed. This also protects the
|
||||
// TokenProvider so it can be used concurrently.
|
||||
//
|
||||
// Config providers used:
|
||||
// * bearerAuthTokenProviderProvider
|
||||
func resolveBearerAuthTokenProvider(ctx context.Context, cfg *aws.Config, configs configs) (bool, error) {
|
||||
tokenProvider, found, err := getBearerAuthTokenProvider(ctx, configs)
|
||||
if !found || err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
cfg.BearerAuthTokenProvider, err = wrapWithBearerAuthTokenCache(
|
||||
ctx, configs, tokenProvider)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func resolveBearerAuthTokenProviderChain(ctx context.Context, cfg *aws.Config, configs configs) (err error) {
|
||||
_, sharedConfig, _ := getAWSConfigSources(configs)
|
||||
|
||||
var provider smithybearer.TokenProvider
|
||||
|
||||
if sharedConfig.SSOSession != nil {
|
||||
provider, err = resolveBearerAuthSSOTokenProvider(
|
||||
ctx, cfg, sharedConfig.SSOSession, configs)
|
||||
}
|
||||
|
||||
if err == nil && provider != nil {
|
||||
cfg.BearerAuthTokenProvider, err = wrapWithBearerAuthTokenCache(
|
||||
ctx, configs, provider)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func resolveBearerAuthSSOTokenProvider(ctx context.Context, cfg *aws.Config, session *SSOSession, configs configs) (*ssocreds.SSOTokenProvider, error) {
|
||||
ssoTokenProviderOptionsFn, found, err := getSSOTokenProviderOptions(ctx, configs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get SSOTokenProviderOptions from config sources, %w", err)
|
||||
}
|
||||
|
||||
var optFns []func(*ssocreds.SSOTokenProviderOptions)
|
||||
if found {
|
||||
optFns = append(optFns, ssoTokenProviderOptionsFn)
|
||||
}
|
||||
|
||||
cachePath, err := ssocreds.StandardCachedTokenFilepath(session.Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get SSOTokenProvider's cache path, %w", err)
|
||||
}
|
||||
|
||||
client := ssooidc.NewFromConfig(*cfg)
|
||||
provider := ssocreds.NewSSOTokenProvider(client, cachePath, optFns...)
|
||||
|
||||
return provider, nil
|
||||
}
|
||||
|
||||
// wrapWithBearerAuthTokenCache will wrap provider with an smithy-go
|
||||
// bearer/auth#TokenCache with the provided options if the provider is not
|
||||
// already a TokenCache.
|
||||
func wrapWithBearerAuthTokenCache(
|
||||
ctx context.Context,
|
||||
cfgs configs,
|
||||
provider smithybearer.TokenProvider,
|
||||
optFns ...func(*smithybearer.TokenCacheOptions),
|
||||
) (smithybearer.TokenProvider, error) {
|
||||
_, ok := provider.(*smithybearer.TokenCache)
|
||||
if ok {
|
||||
return provider, nil
|
||||
}
|
||||
|
||||
tokenCacheConfigOptions, optionsFound, err := getBearerAuthTokenCacheOptions(ctx, cfgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
opts := make([]func(*smithybearer.TokenCacheOptions), 0, 2+len(optFns))
|
||||
opts = append(opts, func(o *smithybearer.TokenCacheOptions) {
|
||||
o.RefreshBeforeExpires = 5 * time.Minute
|
||||
o.RetrieveBearerTokenTimeout = 30 * time.Second
|
||||
})
|
||||
opts = append(opts, optFns...)
|
||||
if optionsFound {
|
||||
opts = append(opts, tokenCacheConfigOptions)
|
||||
}
|
||||
|
||||
return smithybearer.NewTokenCache(provider, opts...), nil
|
||||
}
|
@ -1,63 +1,71 @@
|
||||
// Package ssocreds provides a credential provider for retrieving temporary AWS credentials using an SSO access token.
|
||||
// Package ssocreds provides a credential provider for retrieving temporary AWS
|
||||
// credentials using an SSO access token.
|
||||
//
|
||||
// IMPORTANT: The provider in this package does not initiate or perform the AWS SSO login flow. The SDK provider
|
||||
// expects that you have already performed the SSO login flow using AWS CLI using the "aws sso login" command, or by
|
||||
// some other mechanism. The provider must find a valid non-expired access token for the AWS SSO user portal URL in
|
||||
// ~/.aws/sso/cache. If a cached token is not found, it is expired, or the file is malformed an error will be returned.
|
||||
// IMPORTANT: The provider in this package does not initiate or perform the AWS
|
||||
// SSO login flow. The SDK provider expects that you have already performed the
|
||||
// SSO login flow using AWS CLI using the "aws sso login" command, or by some
|
||||
// other mechanism. The provider must find a valid non-expired access token for
|
||||
// the AWS SSO user portal URL in ~/.aws/sso/cache. If a cached token is not
|
||||
// found, it is expired, or the file is malformed an error will be returned.
|
||||
//
|
||||
// Loading AWS SSO credentials with the AWS shared configuration file
|
||||
// # Loading AWS SSO credentials with the AWS shared configuration file
|
||||
//
|
||||
// You can use configure AWS SSO credentials from the AWS shared configuration file by
|
||||
// providing the specifying the required keys in the profile:
|
||||
//
|
||||
// sso_account_id
|
||||
// sso_region
|
||||
// sso_role_name
|
||||
// sso_start_url
|
||||
// sso_account_id
|
||||
// sso_region
|
||||
// sso_role_name
|
||||
// sso_start_url
|
||||
//
|
||||
// For example, the following defines a profile "devsso" and specifies the AWS SSO parameters that defines the target
|
||||
// account, role, sign-on portal, and the region where the user portal is located. Note: all SSO arguments must be
|
||||
// For example, the following defines a profile "devsso" and specifies the AWS
|
||||
// SSO parameters that defines the target account, role, sign-on portal, and
|
||||
// the region where the user portal is located. Note: all SSO arguments must be
|
||||
// provided, or an error will be returned.
|
||||
//
|
||||
// [profile devsso]
|
||||
// sso_start_url = https://my-sso-portal.awsapps.com/start
|
||||
// sso_role_name = SSOReadOnlyRole
|
||||
// sso_region = us-east-1
|
||||
// sso_account_id = 123456789012
|
||||
// [profile devsso]
|
||||
// sso_start_url = https://my-sso-portal.awsapps.com/start
|
||||
// sso_role_name = SSOReadOnlyRole
|
||||
// sso_region = us-east-1
|
||||
// sso_account_id = 123456789012
|
||||
//
|
||||
// Using the config module, you can load the AWS SDK shared configuration, and specify that this profile be used to
|
||||
// retrieve credentials. For example:
|
||||
// Using the config module, you can load the AWS SDK shared configuration, and
|
||||
// specify that this profile be used to retrieve credentials. For example:
|
||||
//
|
||||
// config, err := config.LoadDefaultConfig(context.TODO(), config.WithSharedConfigProfile("devsso"))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// config, err := config.LoadDefaultConfig(context.TODO(), config.WithSharedConfigProfile("devsso"))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// Programmatically loading AWS SSO credentials directly
|
||||
// # Programmatically loading AWS SSO credentials directly
|
||||
//
|
||||
// You can programmatically construct the AWS SSO Provider in your application, and provide the necessary information
|
||||
// to load and retrieve temporary credentials using an access token from ~/.aws/sso/cache.
|
||||
// You can programmatically construct the AWS SSO Provider in your application,
|
||||
// and provide the necessary information to load and retrieve temporary
|
||||
// credentials using an access token from ~/.aws/sso/cache.
|
||||
//
|
||||
// client := sso.NewFromConfig(cfg)
|
||||
// client := sso.NewFromConfig(cfg)
|
||||
//
|
||||
// var provider aws.CredentialsProvider
|
||||
// provider = ssocreds.New(client, "123456789012", "SSOReadOnlyRole", "us-east-1", "https://my-sso-portal.awsapps.com/start")
|
||||
// var provider aws.CredentialsProvider
|
||||
// provider = ssocreds.New(client, "123456789012", "SSOReadOnlyRole", "us-east-1", "https://my-sso-portal.awsapps.com/start")
|
||||
//
|
||||
// // Wrap the provider with aws.CredentialsCache to cache the credentials until their expire time
|
||||
// provider = aws.NewCredentialsCache(provider)
|
||||
// // Wrap the provider with aws.CredentialsCache to cache the credentials until their expire time
|
||||
// provider = aws.NewCredentialsCache(provider)
|
||||
//
|
||||
// credentials, err := provider.Retrieve(context.TODO())
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// credentials, err := provider.Retrieve(context.TODO())
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// It is important that you wrap the Provider with aws.CredentialsCache if you are programmatically constructing the
|
||||
// provider directly. This prevents your application from accessing the cached access token and requesting new
|
||||
// It is important that you wrap the Provider with aws.CredentialsCache if you
|
||||
// are programmatically constructing the provider directly. This prevents your
|
||||
// application from accessing the cached access token and requesting new
|
||||
// credentials each time the credentials are used.
|
||||
//
|
||||
// Additional Resources
|
||||
// # Additional Resources
|
||||
//
|
||||
// Configuring the AWS CLI to use AWS Single Sign-On: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html
|
||||
// Configuring the AWS CLI to use AWS Single Sign-On:
|
||||
// https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html
|
||||
//
|
||||
// AWS Single Sign-On User Guide: https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html
|
||||
// AWS Single Sign-On User Guide:
|
||||
// https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html
|
||||
package ssocreds
|
||||
|
@ -1,10 +0,0 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package ssocreds
|
||||
|
||||
import "os"
|
||||
|
||||
func getHomeDirectory() string {
|
||||
return os.Getenv("HOME")
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package ssocreds
|
||||
|
||||
import "os"
|
||||
|
||||
func getHomeDirectory() string {
|
||||
return os.Getenv("USERPROFILE")
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
package ssocreds
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/internal/sdk"
|
||||
"github.com/aws/aws-sdk-go-v2/service/sso"
|
||||
)
|
||||
|
||||
// ProviderName is the name of the provider used to specify the source of credentials.
|
||||
const ProviderName = "SSOProvider"
|
||||
|
||||
var defaultCacheLocation func() string
|
||||
|
||||
func defaultCacheLocationImpl() string {
|
||||
return filepath.Join(getHomeDirectory(), ".aws", "sso", "cache")
|
||||
}
|
||||
|
||||
func init() {
|
||||
defaultCacheLocation = defaultCacheLocationImpl
|
||||
}
|
||||
|
||||
// GetRoleCredentialsAPIClient is a API client that implements the GetRoleCredentials operation.
|
||||
type GetRoleCredentialsAPIClient interface {
|
||||
GetRoleCredentials(ctx context.Context, params *sso.GetRoleCredentialsInput, optFns ...func(*sso.Options)) (*sso.GetRoleCredentialsOutput, error)
|
||||
}
|
||||
|
||||
// Options is the Provider options structure.
|
||||
type Options struct {
|
||||
// The Client which is configured for the AWS Region where the AWS SSO user portal is located.
|
||||
Client GetRoleCredentialsAPIClient
|
||||
|
||||
// The AWS account that is assigned to the user.
|
||||
AccountID string
|
||||
|
||||
// The role name that is assigned to the user.
|
||||
RoleName string
|
||||
|
||||
// The URL that points to the organization's AWS Single Sign-On (AWS SSO) user portal.
|
||||
StartURL string
|
||||
}
|
||||
|
||||
// Provider is an AWS credential provider that retrieves temporary AWS credentials by exchanging an SSO login token.
|
||||
type Provider struct {
|
||||
options Options
|
||||
}
|
||||
|
||||
// New returns a new AWS Single Sign-On (AWS SSO) credential provider. The provided client is expected to be configured
|
||||
// for the AWS Region where the AWS SSO user portal is located.
|
||||
func New(client GetRoleCredentialsAPIClient, accountID, roleName, startURL string, optFns ...func(options *Options)) *Provider {
|
||||
options := Options{
|
||||
Client: client,
|
||||
AccountID: accountID,
|
||||
RoleName: roleName,
|
||||
StartURL: startURL,
|
||||
}
|
||||
|
||||
for _, fn := range optFns {
|
||||
fn(&options)
|
||||
}
|
||||
|
||||
return &Provider{
|
||||
options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve retrieves temporary AWS credentials from the configured Amazon Single Sign-On (AWS SSO) user portal
|
||||
// by exchanging the accessToken present in ~/.aws/sso/cache.
|
||||
func (p *Provider) Retrieve(ctx context.Context) (aws.Credentials, error) {
|
||||
tokenFile, err := loadTokenFile(p.options.StartURL)
|
||||
if err != nil {
|
||||
return aws.Credentials{}, err
|
||||
}
|
||||
|
||||
output, err := p.options.Client.GetRoleCredentials(ctx, &sso.GetRoleCredentialsInput{
|
||||
AccessToken: &tokenFile.AccessToken,
|
||||
AccountId: &p.options.AccountID,
|
||||
RoleName: &p.options.RoleName,
|
||||
})
|
||||
if err != nil {
|
||||
return aws.Credentials{}, err
|
||||
}
|
||||
|
||||
return aws.Credentials{
|
||||
AccessKeyID: aws.ToString(output.RoleCredentials.AccessKeyId),
|
||||
SecretAccessKey: aws.ToString(output.RoleCredentials.SecretAccessKey),
|
||||
SessionToken: aws.ToString(output.RoleCredentials.SessionToken),
|
||||
Expires: time.Unix(0, output.RoleCredentials.Expiration*int64(time.Millisecond)).UTC(),
|
||||
CanExpire: true,
|
||||
Source: ProviderName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getCacheFileName(url string) (string, error) {
|
||||
hash := sha1.New()
|
||||
_, err := hash.Write([]byte(url))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.ToLower(hex.EncodeToString(hash.Sum(nil))) + ".json", nil
|
||||
}
|
||||
|
||||
type rfc3339 time.Time
|
||||
|
||||
func (r *rfc3339) UnmarshalJSON(bytes []byte) error {
|
||||
var value string
|
||||
|
||||
if err := json.Unmarshal(bytes, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parse, err := time.Parse(time.RFC3339, value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("expected RFC3339 timestamp: %w", err)
|
||||
}
|
||||
|
||||
*r = rfc3339(parse)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type token struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
ExpiresAt rfc3339 `json:"expiresAt"`
|
||||
Region string `json:"region,omitempty"`
|
||||
StartURL string `json:"startUrl,omitempty"`
|
||||
}
|
||||
|
||||
func (t token) Expired() bool {
|
||||
return sdk.NowTime().Round(0).After(time.Time(t.ExpiresAt))
|
||||
}
|
||||
|
||||
// InvalidTokenError is the error type that is returned if loaded token has expired or is otherwise invalid.
|
||||
// To refresh the SSO session run aws sso login with the corresponding profile.
|
||||
type InvalidTokenError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (i *InvalidTokenError) Unwrap() error {
|
||||
return i.Err
|
||||
}
|
||||
|
||||
func (i *InvalidTokenError) Error() string {
|
||||
const msg = "the SSO session has expired or is invalid"
|
||||
if i.Err == nil {
|
||||
return msg
|
||||
}
|
||||
return msg + ": " + i.Err.Error()
|
||||
}
|
||||
|
||||
func loadTokenFile(startURL string) (t token, err error) {
|
||||
key, err := getCacheFileName(startURL)
|
||||
if err != nil {
|
||||
return token{}, &InvalidTokenError{Err: err}
|
||||
}
|
||||
|
||||
fileBytes, err := ioutil.ReadFile(filepath.Join(defaultCacheLocation(), key))
|
||||
if err != nil {
|
||||
return token{}, &InvalidTokenError{Err: err}
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(fileBytes, &t); err != nil {
|
||||
return token{}, &InvalidTokenError{Err: err}
|
||||
}
|
||||
|
||||
if len(t.AccessToken) == 0 {
|
||||
return token{}, &InvalidTokenError{}
|
||||
}
|
||||
|
||||
if t.Expired() {
|
||||
return token{}, &InvalidTokenError{Err: fmt.Errorf("access token is expired")}
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
@ -0,0 +1,233 @@
|
||||
package ssocreds
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/internal/sdk"
|
||||
"github.com/aws/aws-sdk-go-v2/internal/shareddefaults"
|
||||
)
|
||||
|
||||
var osUserHomeDur = shareddefaults.UserHomeDir
|
||||
|
||||
// StandardCachedTokenFilepath returns the filepath for the cached SSO token file, or
|
||||
// error if unable get derive the path. Key that will be used to compute a SHA1
|
||||
// value that is hex encoded.
|
||||
//
|
||||
// Derives the filepath using the Key as:
|
||||
//
|
||||
// ~/.aws/sso/cache/<sha1-hex-encoded-key>.json
|
||||
func StandardCachedTokenFilepath(key string) (string, error) {
|
||||
homeDir := osUserHomeDur()
|
||||
if len(homeDir) == 0 {
|
||||
return "", fmt.Errorf("unable to get USER's home directory for cached token")
|
||||
}
|
||||
hash := sha1.New()
|
||||
if _, err := hash.Write([]byte(key)); err != nil {
|
||||
return "", fmt.Errorf("unable to compute cached token filepath key SHA1 hash, %w", err)
|
||||
}
|
||||
|
||||
cacheFilename := strings.ToLower(hex.EncodeToString(hash.Sum(nil))) + ".json"
|
||||
|
||||
return filepath.Join(homeDir, ".aws", "sso", "cache", cacheFilename), nil
|
||||
}
|
||||
|
||||
type tokenKnownFields struct {
|
||||
AccessToken string `json:"accessToken,omitempty"`
|
||||
ExpiresAt *rfc3339 `json:"expiresAt,omitempty"`
|
||||
|
||||
RefreshToken string `json:"refreshToken,omitempty"`
|
||||
ClientID string `json:"clientId,omitempty"`
|
||||
ClientSecret string `json:"clientSecret,omitempty"`
|
||||
}
|
||||
|
||||
type token struct {
|
||||
tokenKnownFields
|
||||
UnknownFields map[string]interface{} `json:"-"`
|
||||
}
|
||||
|
||||
func (t token) MarshalJSON() ([]byte, error) {
|
||||
fields := map[string]interface{}{}
|
||||
|
||||
setTokenFieldString(fields, "accessToken", t.AccessToken)
|
||||
setTokenFieldRFC3339(fields, "expiresAt", t.ExpiresAt)
|
||||
|
||||
setTokenFieldString(fields, "refreshToken", t.RefreshToken)
|
||||
setTokenFieldString(fields, "clientId", t.ClientID)
|
||||
setTokenFieldString(fields, "clientSecret", t.ClientSecret)
|
||||
|
||||
for k, v := range t.UnknownFields {
|
||||
if _, ok := fields[k]; ok {
|
||||
return nil, fmt.Errorf("unknown token field %v, duplicates known field", k)
|
||||
}
|
||||
fields[k] = v
|
||||
}
|
||||
|
||||
return json.Marshal(fields)
|
||||
}
|
||||
|
||||
func setTokenFieldString(fields map[string]interface{}, key, value string) {
|
||||
if value == "" {
|
||||
return
|
||||
}
|
||||
fields[key] = value
|
||||
}
|
||||
func setTokenFieldRFC3339(fields map[string]interface{}, key string, value *rfc3339) {
|
||||
if value == nil {
|
||||
return
|
||||
}
|
||||
fields[key] = value
|
||||
}
|
||||
|
||||
func (t *token) UnmarshalJSON(b []byte) error {
|
||||
var fields map[string]interface{}
|
||||
if err := json.Unmarshal(b, &fields); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
t.UnknownFields = map[string]interface{}{}
|
||||
|
||||
for k, v := range fields {
|
||||
var err error
|
||||
switch k {
|
||||
case "accessToken":
|
||||
err = getTokenFieldString(v, &t.AccessToken)
|
||||
case "expiresAt":
|
||||
err = getTokenFieldRFC3339(v, &t.ExpiresAt)
|
||||
case "refreshToken":
|
||||
err = getTokenFieldString(v, &t.RefreshToken)
|
||||
case "clientId":
|
||||
err = getTokenFieldString(v, &t.ClientID)
|
||||
case "clientSecret":
|
||||
err = getTokenFieldString(v, &t.ClientSecret)
|
||||
default:
|
||||
t.UnknownFields[k] = v
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("field %q, %w", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTokenFieldString(v interface{}, value *string) error {
|
||||
var ok bool
|
||||
*value, ok = v.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("expect value to be string, got %T", v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTokenFieldRFC3339(v interface{}, value **rfc3339) error {
|
||||
var stringValue string
|
||||
if err := getTokenFieldString(v, &stringValue); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
timeValue, err := parseRFC3339(stringValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*value = &timeValue
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadCachedToken(filename string) (token, error) {
|
||||
fileBytes, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return token{}, fmt.Errorf("failed to read cached SSO token file, %w", err)
|
||||
}
|
||||
|
||||
var t token
|
||||
if err := json.Unmarshal(fileBytes, &t); err != nil {
|
||||
return token{}, fmt.Errorf("failed to parse cached SSO token file, %w", err)
|
||||
}
|
||||
|
||||
if len(t.AccessToken) == 0 || t.ExpiresAt == nil || time.Time(*t.ExpiresAt).IsZero() {
|
||||
return token{}, fmt.Errorf(
|
||||
"cached SSO token must contain accessToken and expiresAt fields")
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func storeCachedToken(filename string, t token, fileMode os.FileMode) (err error) {
|
||||
tmpFilename := filename + ".tmp-" + strconv.FormatInt(sdk.NowTime().UnixNano(), 10)
|
||||
if err := writeCacheFile(tmpFilename, fileMode, t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.Rename(tmpFilename, filename); err != nil {
|
||||
return fmt.Errorf("failed to replace old cached SSO token file, %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeCacheFile(filename string, fileMode os.FileMode, t token) (err error) {
|
||||
var f *os.File
|
||||
f, err = os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_RDWR, fileMode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create cached SSO token file %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
closeErr := f.Close()
|
||||
if err == nil && closeErr != nil {
|
||||
err = fmt.Errorf("failed to close cached SSO token file, %w", closeErr)
|
||||
}
|
||||
}()
|
||||
|
||||
encoder := json.NewEncoder(f)
|
||||
|
||||
if err = encoder.Encode(t); err != nil {
|
||||
return fmt.Errorf("failed to serialize cached SSO token, %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type rfc3339 time.Time
|
||||
|
||||
func parseRFC3339(v string) (rfc3339, error) {
|
||||
parsed, err := time.Parse(time.RFC3339, v)
|
||||
if err != nil {
|
||||
return rfc3339{}, fmt.Errorf("expected RFC3339 timestamp: %w", err)
|
||||
}
|
||||
|
||||
return rfc3339(parsed), nil
|
||||
}
|
||||
|
||||
func (r *rfc3339) UnmarshalJSON(bytes []byte) (err error) {
|
||||
var value string
|
||||
|
||||
// Use JSON unmarshal to unescape the quoted value making use of JSON's
|
||||
// unquoting rules.
|
||||
if err = json.Unmarshal(bytes, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*r, err = parseRFC3339(value)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *rfc3339) MarshalJSON() ([]byte, error) {
|
||||
value := time.Time(*r).Format(time.RFC3339)
|
||||
|
||||
// Use JSON unmarshal to unescape the quoted value making use of JSON's
|
||||
// quoting rules.
|
||||
return json.Marshal(value)
|
||||
}
|
152
vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/sso_credentials_provider.go
generated
vendored
152
vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/sso_credentials_provider.go
generated
vendored
@ -0,0 +1,152 @@
|
||||
package ssocreds
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/internal/sdk"
|
||||
"github.com/aws/aws-sdk-go-v2/service/sso"
|
||||
)
|
||||
|
||||
// ProviderName is the name of the provider used to specify the source of
|
||||
// credentials.
|
||||
const ProviderName = "SSOProvider"
|
||||
|
||||
// GetRoleCredentialsAPIClient is a API client that implements the
|
||||
// GetRoleCredentials operation.
|
||||
type GetRoleCredentialsAPIClient interface {
|
||||
GetRoleCredentials(context.Context, *sso.GetRoleCredentialsInput, ...func(*sso.Options)) (
|
||||
*sso.GetRoleCredentialsOutput, error,
|
||||
)
|
||||
}
|
||||
|
||||
// Options is the Provider options structure.
|
||||
type Options struct {
|
||||
// The Client which is configured for the AWS Region where the AWS SSO user
|
||||
// portal is located.
|
||||
Client GetRoleCredentialsAPIClient
|
||||
|
||||
// The AWS account that is assigned to the user.
|
||||
AccountID string
|
||||
|
||||
// The role name that is assigned to the user.
|
||||
RoleName string
|
||||
|
||||
// The URL that points to the organization's AWS Single Sign-On (AWS SSO)
|
||||
// user portal.
|
||||
StartURL string
|
||||
|
||||
// The filepath the cached token will be retrieved from. If unset Provider will
|
||||
// use the startURL to determine the filepath at.
|
||||
//
|
||||
// ~/.aws/sso/cache/<sha1-hex-encoded-startURL>.json
|
||||
//
|
||||
// If custom cached token filepath is used, the Provider's startUrl
|
||||
// parameter will be ignored.
|
||||
CachedTokenFilepath string
|
||||
|
||||
// Used by the SSOCredentialProvider if a token configuration
|
||||
// profile is used in the shared config
|
||||
SSOTokenProvider *SSOTokenProvider
|
||||
}
|
||||
|
||||
// Provider is an AWS credential provider that retrieves temporary AWS
|
||||
// credentials by exchanging an SSO login token.
|
||||
type Provider struct {
|
||||
options Options
|
||||
|
||||
cachedTokenFilepath string
|
||||
}
|
||||
|
||||
// New returns a new AWS Single Sign-On (AWS SSO) credential provider. The
|
||||
// provided client is expected to be configured for the AWS Region where the
|
||||
// AWS SSO user portal is located.
|
||||
func New(client GetRoleCredentialsAPIClient, accountID, roleName, startURL string, optFns ...func(options *Options)) *Provider {
|
||||
options := Options{
|
||||
Client: client,
|
||||
AccountID: accountID,
|
||||
RoleName: roleName,
|
||||
StartURL: startURL,
|
||||
}
|
||||
|
||||
for _, fn := range optFns {
|
||||
fn(&options)
|
||||
}
|
||||
|
||||
return &Provider{
|
||||
options: options,
|
||||
cachedTokenFilepath: options.CachedTokenFilepath,
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve retrieves temporary AWS credentials from the configured Amazon
|
||||
// Single Sign-On (AWS SSO) user portal by exchanging the accessToken present
|
||||
// in ~/.aws/sso/cache. However, if a token provider configuration exists
|
||||
// in the shared config, then we ought to use the token provider rather then
|
||||
// direct access on the cached token.
|
||||
func (p *Provider) Retrieve(ctx context.Context) (aws.Credentials, error) {
|
||||
var accessToken *string
|
||||
if p.options.SSOTokenProvider != nil {
|
||||
token, err := p.options.SSOTokenProvider.RetrieveBearerToken(ctx)
|
||||
if err != nil {
|
||||
return aws.Credentials{}, err
|
||||
}
|
||||
accessToken = &token.Value
|
||||
} else {
|
||||
if p.cachedTokenFilepath == "" {
|
||||
cachedTokenFilepath, err := StandardCachedTokenFilepath(p.options.StartURL)
|
||||
if err != nil {
|
||||
return aws.Credentials{}, &InvalidTokenError{Err: err}
|
||||
}
|
||||
p.cachedTokenFilepath = cachedTokenFilepath
|
||||
}
|
||||
|
||||
tokenFile, err := loadCachedToken(p.cachedTokenFilepath)
|
||||
if err != nil {
|
||||
return aws.Credentials{}, &InvalidTokenError{Err: err}
|
||||
}
|
||||
|
||||
if tokenFile.ExpiresAt == nil || sdk.NowTime().After(time.Time(*tokenFile.ExpiresAt)) {
|
||||
return aws.Credentials{}, &InvalidTokenError{}
|
||||
}
|
||||
accessToken = &tokenFile.AccessToken
|
||||
}
|
||||
|
||||
output, err := p.options.Client.GetRoleCredentials(ctx, &sso.GetRoleCredentialsInput{
|
||||
AccessToken: accessToken,
|
||||
AccountId: &p.options.AccountID,
|
||||
RoleName: &p.options.RoleName,
|
||||
})
|
||||
if err != nil {
|
||||
return aws.Credentials{}, err
|
||||
}
|
||||
|
||||
return aws.Credentials{
|
||||
AccessKeyID: aws.ToString(output.RoleCredentials.AccessKeyId),
|
||||
SecretAccessKey: aws.ToString(output.RoleCredentials.SecretAccessKey),
|
||||
SessionToken: aws.ToString(output.RoleCredentials.SessionToken),
|
||||
CanExpire: true,
|
||||
Expires: time.Unix(0, output.RoleCredentials.Expiration*int64(time.Millisecond)).UTC(),
|
||||
Source: ProviderName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// InvalidTokenError is the error type that is returned if loaded token has
|
||||
// expired or is otherwise invalid. To refresh the SSO session run AWS SSO
|
||||
// login with the corresponding profile.
|
||||
type InvalidTokenError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (i *InvalidTokenError) Unwrap() error {
|
||||
return i.Err
|
||||
}
|
||||
|
||||
func (i *InvalidTokenError) Error() string {
|
||||
const msg = "the SSO session has expired or is invalid"
|
||||
if i.Err == nil {
|
||||
return msg
|
||||
}
|
||||
return msg + ": " + i.Err.Error()
|
||||
}
|
147
vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/sso_token_provider.go
generated
vendored
147
vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/sso_token_provider.go
generated
vendored
@ -0,0 +1,147 @@
|
||||
package ssocreds
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/internal/sdk"
|
||||
"github.com/aws/aws-sdk-go-v2/service/ssooidc"
|
||||
"github.com/aws/smithy-go/auth/bearer"
|
||||
)
|
||||
|
||||
// CreateTokenAPIClient provides the interface for the SSOTokenProvider's API
|
||||
// client for calling CreateToken operation to refresh the SSO token.
|
||||
type CreateTokenAPIClient interface {
|
||||
CreateToken(context.Context, *ssooidc.CreateTokenInput, ...func(*ssooidc.Options)) (
|
||||
*ssooidc.CreateTokenOutput, error,
|
||||
)
|
||||
}
|
||||
|
||||
// SSOTokenProviderOptions provides the options for configuring the
|
||||
// SSOTokenProvider.
|
||||
type SSOTokenProviderOptions struct {
|
||||
// Client that can be overridden
|
||||
Client CreateTokenAPIClient
|
||||
|
||||
// The set of API Client options to be applied when invoking the
|
||||
// CreateToken operation.
|
||||
ClientOptions []func(*ssooidc.Options)
|
||||
|
||||
// The path the file containing the cached SSO token will be read from.
|
||||
// Initialized the NewSSOTokenProvider's cachedTokenFilepath parameter.
|
||||
CachedTokenFilepath string
|
||||
}
|
||||
|
||||
// SSOTokenProvider provides an utility for refreshing SSO AccessTokens for
|
||||
// Bearer Authentication. The SSOTokenProvider can only be used to refresh
|
||||
// already cached SSO Tokens. This utility cannot perform the initial SSO
|
||||
// create token.
|
||||
//
|
||||
// The SSOTokenProvider is not safe to use concurrently. It must be wrapped in
|
||||
// a utility such as smithy-go's auth/bearer#TokenCache. The SDK's
|
||||
// config.LoadDefaultConfig will automatically wrap the SSOTokenProvider with
|
||||
// the smithy-go TokenCache, if the external configuration loaded configured
|
||||
// for an SSO session.
|
||||
//
|
||||
// The initial SSO create token should be preformed with the AWS CLI before the
|
||||
// Go application using the SSOTokenProvider will need to retrieve the SSO
|
||||
// token. If the AWS CLI has not created the token cache file, this provider
|
||||
// will return an error when attempting to retrieve the cached token.
|
||||
//
|
||||
// This provider will attempt to refresh the cached SSO token periodically if
|
||||
// needed when RetrieveBearerToken is called.
|
||||
//
|
||||
// A utility such as the AWS CLI must be used to initially create the SSO
|
||||
// session and cached token file.
|
||||
// https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html
|
||||
type SSOTokenProvider struct {
|
||||
options SSOTokenProviderOptions
|
||||
}
|
||||
|
||||
var _ bearer.TokenProvider = (*SSOTokenProvider)(nil)
|
||||
|
||||
// NewSSOTokenProvider returns an initialized SSOTokenProvider that will
|
||||
// periodically refresh the SSO token cached stored in the cachedTokenFilepath.
|
||||
// The cachedTokenFilepath file's content will be rewritten by the token
|
||||
// provider when the token is refreshed.
|
||||
//
|
||||
// The client must be configured for the AWS region the SSO token was created for.
|
||||
func NewSSOTokenProvider(client CreateTokenAPIClient, cachedTokenFilepath string, optFns ...func(o *SSOTokenProviderOptions)) *SSOTokenProvider {
|
||||
options := SSOTokenProviderOptions{
|
||||
Client: client,
|
||||
CachedTokenFilepath: cachedTokenFilepath,
|
||||
}
|
||||
for _, fn := range optFns {
|
||||
fn(&options)
|
||||
}
|
||||
|
||||
provider := &SSOTokenProvider{
|
||||
options: options,
|
||||
}
|
||||
|
||||
return provider
|
||||
}
|
||||
|
||||
// RetrieveBearerToken returns the SSO token stored in the cachedTokenFilepath
|
||||
// the SSOTokenProvider was created with. If the token has expired
|
||||
// RetrieveBearerToken will attempt to refresh it. If the token cannot be
|
||||
// refreshed or is not present an error will be returned.
|
||||
//
|
||||
// A utility such as the AWS CLI must be used to initially create the SSO
|
||||
// session and cached token file. https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html
|
||||
func (p SSOTokenProvider) RetrieveBearerToken(ctx context.Context) (bearer.Token, error) {
|
||||
cachedToken, err := loadCachedToken(p.options.CachedTokenFilepath)
|
||||
if err != nil {
|
||||
return bearer.Token{}, err
|
||||
}
|
||||
|
||||
if cachedToken.ExpiresAt != nil && sdk.NowTime().After(time.Time(*cachedToken.ExpiresAt)) {
|
||||
cachedToken, err = p.refreshToken(ctx, cachedToken)
|
||||
if err != nil {
|
||||
return bearer.Token{}, fmt.Errorf("refresh cached SSO token failed, %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
expiresAt := aws.ToTime((*time.Time)(cachedToken.ExpiresAt))
|
||||
return bearer.Token{
|
||||
Value: cachedToken.AccessToken,
|
||||
CanExpire: !expiresAt.IsZero(),
|
||||
Expires: expiresAt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p SSOTokenProvider) refreshToken(ctx context.Context, cachedToken token) (token, error) {
|
||||
if cachedToken.ClientSecret == "" || cachedToken.ClientID == "" || cachedToken.RefreshToken == "" {
|
||||
return token{}, fmt.Errorf("cached SSO token is expired, or not present, and cannot be refreshed")
|
||||
}
|
||||
|
||||
createResult, err := p.options.Client.CreateToken(ctx, &ssooidc.CreateTokenInput{
|
||||
ClientId: &cachedToken.ClientID,
|
||||
ClientSecret: &cachedToken.ClientSecret,
|
||||
RefreshToken: &cachedToken.RefreshToken,
|
||||
GrantType: aws.String("refresh_token"),
|
||||
}, p.options.ClientOptions...)
|
||||
if err != nil {
|
||||
return token{}, fmt.Errorf("unable to refresh SSO token, %w", err)
|
||||
}
|
||||
|
||||
expiresAt := sdk.NowTime().Add(time.Duration(createResult.ExpiresIn) * time.Second)
|
||||
|
||||
cachedToken.AccessToken = aws.ToString(createResult.AccessToken)
|
||||
cachedToken.ExpiresAt = (*rfc3339)(&expiresAt)
|
||||
cachedToken.RefreshToken = aws.ToString(createResult.RefreshToken)
|
||||
|
||||
fileInfo, err := os.Stat(p.options.CachedTokenFilepath)
|
||||
if err != nil {
|
||||
return token{}, fmt.Errorf("failed to stat cached SSO token file %w", err)
|
||||
}
|
||||
|
||||
if err = storeCachedToken(p.options.CachedTokenFilepath, cachedToken, fileInfo.Mode()); err != nil {
|
||||
return token{}, fmt.Errorf("unable to cache refreshed SSO token, %w", err)
|
||||
}
|
||||
|
||||
return cachedToken, nil
|
||||
}
|
98
vendor/github.com/aws/aws-sdk-go-v2/credentials/stscreds/assume_role_provider.go
generated
vendored
98
vendor/github.com/aws/aws-sdk-go-v2/credentials/stscreds/assume_role_provider.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go
generated
vendored
@ -1,18 +0,0 @@
|
||||
//go:build gofuzz
|
||||
// +build gofuzz
|
||||
|
||||
package ini
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
b := bytes.NewReader(data)
|
||||
|
||||
if _, err := Parse(b); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package shareddefaults
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// SharedCredentialsFilename returns the SDK's default file path
|
||||
// for the shared credentials file.
|
||||
//
|
||||
// Builds the shared config file path based on the OS's platform.
|
||||
//
|
||||
// - Linux/Unix: $HOME/.aws/credentials
|
||||
// - Windows: %USERPROFILE%\.aws\credentials
|
||||
func SharedCredentialsFilename() string {
|
||||
return filepath.Join(UserHomeDir(), ".aws", "credentials")
|
||||
}
|
||||
|
||||
// SharedConfigFilename returns the SDK's default file path for
|
||||
// the shared config file.
|
||||
//
|
||||
// Builds the shared config file path based on the OS's platform.
|
||||
//
|
||||
// - Linux/Unix: $HOME/.aws/config
|
||||
// - Windows: %USERPROFILE%\.aws\config
|
||||
func SharedConfigFilename() string {
|
||||
return filepath.Join(UserHomeDir(), ".aws", "config")
|
||||
}
|
||||
|
||||
// UserHomeDir returns the home directory for the user the process is
|
||||
// running under.
|
||||
func UserHomeDir() string {
|
||||
// Ignore errors since we only care about Windows and *nix.
|
||||
home, _ := os.UserHomeDir()
|
||||
|
||||
if len(home) > 0 {
|
||||
return home
|
||||
}
|
||||
|
||||
currUser, _ := user.Current()
|
||||
if currUser != nil {
|
||||
home = currUser.HomeDir
|
||||
}
|
||||
|
||||
return home
|
||||
}
|
80
vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md
generated
vendored
80
vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md
generated
vendored
56
vendor/github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints/endpoints.go
generated
vendored
56
vendor/github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints/endpoints.go
generated
vendored
@ -0,0 +1,217 @@
|
||||
# v1.14.5 (2023-03-10)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.14.4 (2023-02-22)
|
||||
|
||||
* **Bug Fix**: Prevent nil pointer dereference when retrieving error codes.
|
||||
|
||||
# v1.14.3 (2023-02-20)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.14.2 (2023-02-15)
|
||||
|
||||
* **Announcement**: When receiving an error response in restJson-based services, an incorrect error type may have been returned based on the content of the response. This has been fixed via PR #2012 tracked in issue #1910.
|
||||
* **Bug Fix**: Correct error type parsing for restJson services.
|
||||
|
||||
# v1.14.1 (2023-02-03)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.14.0 (2023-01-05)
|
||||
|
||||
* **Feature**: Add `ErrorCodeOverride` field to all error structs (aws/smithy-go#401).
|
||||
|
||||
# v1.13.11 (2022-12-19)
|
||||
|
||||
* No change notes available for this release.
|
||||
|
||||
# v1.13.10 (2022-12-15)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.13.9 (2022-12-02)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.13.8 (2022-10-24)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.13.7 (2022-10-21)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.13.6 (2022-09-30)
|
||||
|
||||
* **Documentation**: Documentation updates for the IAM Identity Center OIDC CLI Reference.
|
||||
|
||||
# v1.13.5 (2022-09-20)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.13.4 (2022-09-14)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.13.3 (2022-09-02)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.13.2 (2022-08-31)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.13.1 (2022-08-29)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.13.0 (2022-08-25)
|
||||
|
||||
* **Feature**: Updated required request parameters on IAM Identity Center's OIDC CreateToken action.
|
||||
|
||||
# v1.12.14 (2022-08-11)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.13 (2022-08-09)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.12 (2022-08-08)
|
||||
|
||||
* **Documentation**: Documentation updates to reflect service rename - AWS IAM Identity Center (successor to AWS Single Sign-On)
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.11 (2022-08-01)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.10 (2022-07-11)
|
||||
|
||||
* No change notes available for this release.
|
||||
|
||||
# v1.12.9 (2022-07-05)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.8 (2022-06-29)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.7 (2022-06-07)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.6 (2022-05-27)
|
||||
|
||||
* No change notes available for this release.
|
||||
|
||||
# v1.12.5 (2022-05-17)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.4 (2022-04-25)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.3 (2022-03-30)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.2 (2022-03-24)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.1 (2022-03-23)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.12.0 (2022-03-08)
|
||||
|
||||
* **Feature**: Updated `github.com/aws/smithy-go` to latest version
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.11.0 (2022-02-24)
|
||||
|
||||
* **Feature**: API client updated
|
||||
* **Feature**: Adds RetryMaxAttempts and RetryMod to API client Options. This allows the API clients' default Retryer to be configured from the shared configuration files or environment variables. Adding a new Retry mode of `Adaptive`. `Adaptive` retry mode is an experimental mode, adding client rate limiting when throttles reponses are received from an API. See [retry.AdaptiveMode](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#AdaptiveMode) for more details, and configuration options.
|
||||
* **Feature**: Updated `github.com/aws/smithy-go` to latest version
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.10.0 (2022-01-14)
|
||||
|
||||
* **Feature**: Updated `github.com/aws/smithy-go` to latest version
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.9.0 (2022-01-07)
|
||||
|
||||
* **Feature**: API client updated
|
||||
* **Feature**: Updated `github.com/aws/smithy-go` to latest version
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.8.2 (2021-12-02)
|
||||
|
||||
* **Bug Fix**: Fixes a bug that prevented aws.EndpointResolverWithOptions from being used by the service client. ([#1514](https://github.com/aws/aws-sdk-go-v2/pull/1514))
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.8.1 (2021-11-19)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.8.0 (2021-11-06)
|
||||
|
||||
* **Feature**: The SDK now supports configuration of FIPS and DualStack endpoints using environment variables, shared configuration, or programmatically.
|
||||
* **Feature**: Updated `github.com/aws/smithy-go` to latest version
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.7.0 (2021-10-21)
|
||||
|
||||
* **Feature**: Updated to latest version
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.6.0 (2021-10-11)
|
||||
|
||||
* **Feature**: API client updated
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.5.0 (2021-09-17)
|
||||
|
||||
* **Feature**: Updated API client and endpoints to latest revision.
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.4.0 (2021-08-27)
|
||||
|
||||
* **Feature**: Updated API model to latest revision.
|
||||
* **Feature**: Updated `github.com/aws/smithy-go` to latest version
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.3.3 (2021-08-19)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.3.2 (2021-08-04)
|
||||
|
||||
* **Dependency Update**: Updated `github.com/aws/smithy-go` to latest version.
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.3.1 (2021-07-15)
|
||||
|
||||
* **Dependency Update**: Updated `github.com/aws/smithy-go` to latest version
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.3.0 (2021-06-25)
|
||||
|
||||
* **Feature**: Updated `github.com/aws/smithy-go` to latest version
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.2.1 (2021-05-20)
|
||||
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
||||
# v1.2.0 (2021-05-14)
|
||||
|
||||
* **Feature**: Constant has been added to modules to enable runtime version inspection for reporting.
|
||||
* **Dependency Update**: Updated to the latest SDK module versions
|
||||
|
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -0,0 +1,433 @@
|
||||
// Code generated by smithy-go-codegen DO NOT EDIT.
|
||||
|
||||
package ssooidc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/aws/defaults"
|
||||
awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
|
||||
"github.com/aws/aws-sdk-go-v2/aws/retry"
|
||||
"github.com/aws/aws-sdk-go-v2/aws/signer/v4"
|
||||
awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
|
||||
internalConfig "github.com/aws/aws-sdk-go-v2/internal/configsources"
|
||||
smithy "github.com/aws/smithy-go"
|
||||
smithydocument "github.com/aws/smithy-go/document"
|
||||
"github.com/aws/smithy-go/logging"
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
smithyhttp "github.com/aws/smithy-go/transport/http"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const ServiceID = "SSO OIDC"
|
||||
const ServiceAPIVersion = "2019-06-10"
|
||||
|
||||
// Client provides the API client to make operations call for AWS SSO OIDC.
|
||||
type Client struct {
|
||||
options Options
|
||||
}
|
||||
|
||||
// New returns an initialized Client based on the functional options. Provide
|
||||
// additional functional options to further configure the behavior of the client,
|
||||
// such as changing the client's endpoint or adding custom middleware behavior.
|
||||
func New(options Options, optFns ...func(*Options)) *Client {
|
||||
options = options.Copy()
|
||||
|
||||
resolveDefaultLogger(&options)
|
||||
|
||||
setResolvedDefaultsMode(&options)
|
||||
|
||||
resolveRetryer(&options)
|
||||
|
||||
resolveHTTPClient(&options)
|
||||
|
||||
resolveHTTPSignerV4(&options)
|
||||
|
||||
resolveDefaultEndpointConfiguration(&options)
|
||||
|
||||
for _, fn := range optFns {
|
||||
fn(&options)
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
options: options,
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
// Set of options to modify how an operation is invoked. These apply to all
|
||||
// operations invoked for this client. Use functional options on operation call to
|
||||
// modify this list for per operation behavior.
|
||||
APIOptions []func(*middleware.Stack) error
|
||||
|
||||
// Configures the events that will be sent to the configured logger.
|
||||
ClientLogMode aws.ClientLogMode
|
||||
|
||||
// The credentials object to use when signing requests.
|
||||
Credentials aws.CredentialsProvider
|
||||
|
||||
// The configuration DefaultsMode that the SDK should use when constructing the
|
||||
// clients initial default settings.
|
||||
DefaultsMode aws.DefaultsMode
|
||||
|
||||
// The endpoint options to be used when attempting to resolve an endpoint.
|
||||
EndpointOptions EndpointResolverOptions
|
||||
|
||||
// The service endpoint resolver.
|
||||
EndpointResolver EndpointResolver
|
||||
|
||||
// Signature Version 4 (SigV4) Signer
|
||||
HTTPSignerV4 HTTPSignerV4
|
||||
|
||||
// The logger writer interface to write logging messages to.
|
||||
Logger logging.Logger
|
||||
|
||||
// The region to send requests to. (Required)
|
||||
Region string
|
||||
|
||||
// RetryMaxAttempts specifies the maximum number attempts an API client will call
|
||||
// an operation that fails with a retryable error. A value of 0 is ignored, and
|
||||
// will not be used to configure the API client created default retryer, or modify
|
||||
// per operation call's retry max attempts. When creating a new API Clients this
|
||||
// member will only be used if the Retryer Options member is nil. This value will
|
||||
// be ignored if Retryer is not nil. If specified in an operation call's functional
|
||||
// options with a value that is different than the constructed client's Options,
|
||||
// the Client's Retryer will be wrapped to use the operation's specific
|
||||
// RetryMaxAttempts value.
|
||||
RetryMaxAttempts int
|
||||
|
||||
// RetryMode specifies the retry mode the API client will be created with, if
|
||||
// Retryer option is not also specified. When creating a new API Clients this
|
||||
// member will only be used if the Retryer Options member is nil. This value will
|
||||
// be ignored if Retryer is not nil. Currently does not support per operation call
|
||||
// overrides, may in the future.
|
||||
RetryMode aws.RetryMode
|
||||
|
||||
// Retryer guides how HTTP requests should be retried in case of recoverable
|
||||
// failures. When nil the API client will use a default retryer. The kind of
|
||||
// default retry created by the API client can be changed with the RetryMode
|
||||
// option.
|
||||
Retryer aws.Retryer
|
||||
|
||||
// The RuntimeEnvironment configuration, only populated if the DefaultsMode is set
|
||||
// to DefaultsModeAuto and is initialized using config.LoadDefaultConfig. You
|
||||
// should not populate this structure programmatically, or rely on the values here
|
||||
// within your applications.
|
||||
RuntimeEnvironment aws.RuntimeEnvironment
|
||||
|
||||
// The initial DefaultsMode used when the client options were constructed. If the
|
||||
// DefaultsMode was set to aws.DefaultsModeAuto this will store what the resolved
|
||||
// value was at that point in time. Currently does not support per operation call
|
||||
// overrides, may in the future.
|
||||
resolvedDefaultsMode aws.DefaultsMode
|
||||
|
||||
// The HTTP client to invoke API calls with. Defaults to client's default HTTP
|
||||
// implementation if nil.
|
||||
HTTPClient HTTPClient
|
||||
}
|
||||
|
||||
// WithAPIOptions returns a functional option for setting the Client's APIOptions
|
||||
// option.
|
||||
func WithAPIOptions(optFns ...func(*middleware.Stack) error) func(*Options) {
|
||||
return func(o *Options) {
|
||||
o.APIOptions = append(o.APIOptions, optFns...)
|
||||
}
|
||||
}
|
||||
|
||||
// WithEndpointResolver returns a functional option for setting the Client's
|
||||
// EndpointResolver option.
|
||||
func WithEndpointResolver(v EndpointResolver) func(*Options) {
|
||||
return func(o *Options) {
|
||||
o.EndpointResolver = v
|
||||
}
|
||||
}
|
||||
|
||||
type HTTPClient interface {
|
||||
Do(*http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
// Copy creates a clone where the APIOptions list is deep copied.
|
||||
func (o Options) Copy() Options {
|
||||
to := o
|
||||
to.APIOptions = make([]func(*middleware.Stack) error, len(o.APIOptions))
|
||||
copy(to.APIOptions, o.APIOptions)
|
||||
|
||||
return to
|
||||
}
|
||||
func (c *Client) invokeOperation(ctx context.Context, opID string, params interface{}, optFns []func(*Options), stackFns ...func(*middleware.Stack, Options) error) (result interface{}, metadata middleware.Metadata, err error) {
|
||||
ctx = middleware.ClearStackValues(ctx)
|
||||
stack := middleware.NewStack(opID, smithyhttp.NewStackRequest)
|
||||
options := c.options.Copy()
|
||||
for _, fn := range optFns {
|
||||
fn(&options)
|
||||
}
|
||||
|
||||
finalizeRetryMaxAttemptOptions(&options, *c)
|
||||
|
||||
finalizeClientEndpointResolverOptions(&options)
|
||||
|
||||
for _, fn := range stackFns {
|
||||
if err := fn(stack, options); err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, fn := range options.APIOptions {
|
||||
if err := fn(stack); err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
}
|
||||
|
||||
handler := middleware.DecorateHandler(smithyhttp.NewClientHandler(options.HTTPClient), stack)
|
||||
result, metadata, err = handler.Handle(ctx, params)
|
||||
if err != nil {
|
||||
err = &smithy.OperationError{
|
||||
ServiceID: ServiceID,
|
||||
OperationName: opID,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
return result, metadata, err
|
||||
}
|
||||
|
||||
type noSmithyDocumentSerde = smithydocument.NoSerde
|
||||
|
||||
func resolveDefaultLogger(o *Options) {
|
||||
if o.Logger != nil {
|
||||
return
|
||||
}
|
||||
o.Logger = logging.Nop{}
|
||||
}
|
||||
|
||||
func addSetLoggerMiddleware(stack *middleware.Stack, o Options) error {
|
||||
return middleware.AddSetLoggerMiddleware(stack, o.Logger)
|
||||
}
|
||||
|
||||
func setResolvedDefaultsMode(o *Options) {
|
||||
if len(o.resolvedDefaultsMode) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var mode aws.DefaultsMode
|
||||
mode.SetFromString(string(o.DefaultsMode))
|
||||
|
||||
if mode == aws.DefaultsModeAuto {
|
||||
mode = defaults.ResolveDefaultsModeAuto(o.Region, o.RuntimeEnvironment)
|
||||
}
|
||||
|
||||
o.resolvedDefaultsMode = mode
|
||||
}
|
||||
|
||||
// NewFromConfig returns a new client from the provided config.
|
||||
func NewFromConfig(cfg aws.Config, optFns ...func(*Options)) *Client {
|
||||
opts := Options{
|
||||
Region: cfg.Region,
|
||||
DefaultsMode: cfg.DefaultsMode,
|
||||
RuntimeEnvironment: cfg.RuntimeEnvironment,
|
||||
HTTPClient: cfg.HTTPClient,
|
||||
Credentials: cfg.Credentials,
|
||||
APIOptions: cfg.APIOptions,
|
||||
Logger: cfg.Logger,
|
||||
ClientLogMode: cfg.ClientLogMode,
|
||||
}
|
||||
resolveAWSRetryerProvider(cfg, &opts)
|
||||
resolveAWSRetryMaxAttempts(cfg, &opts)
|
||||
resolveAWSRetryMode(cfg, &opts)
|
||||
resolveAWSEndpointResolver(cfg, &opts)
|
||||
resolveUseDualStackEndpoint(cfg, &opts)
|
||||
resolveUseFIPSEndpoint(cfg, &opts)
|
||||
return New(opts, optFns...)
|
||||
}
|
||||
|
||||
func resolveHTTPClient(o *Options) {
|
||||
var buildable *awshttp.BuildableClient
|
||||
|
||||
if o.HTTPClient != nil {
|
||||
var ok bool
|
||||
buildable, ok = o.HTTPClient.(*awshttp.BuildableClient)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
buildable = awshttp.NewBuildableClient()
|
||||
}
|
||||
|
||||
modeConfig, err := defaults.GetModeConfiguration(o.resolvedDefaultsMode)
|
||||
if err == nil {
|
||||
buildable = buildable.WithDialerOptions(func(dialer *net.Dialer) {
|
||||
if dialerTimeout, ok := modeConfig.GetConnectTimeout(); ok {
|
||||
dialer.Timeout = dialerTimeout
|
||||
}
|
||||
})
|
||||
|
||||
buildable = buildable.WithTransportOptions(func(transport *http.Transport) {
|
||||
if tlsHandshakeTimeout, ok := modeConfig.GetTLSNegotiationTimeout(); ok {
|
||||
transport.TLSHandshakeTimeout = tlsHandshakeTimeout
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
o.HTTPClient = buildable
|
||||
}
|
||||
|
||||
func resolveRetryer(o *Options) {
|
||||
if o.Retryer != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(o.RetryMode) == 0 {
|
||||
modeConfig, err := defaults.GetModeConfiguration(o.resolvedDefaultsMode)
|
||||
if err == nil {
|
||||
o.RetryMode = modeConfig.RetryMode
|
||||
}
|
||||
}
|
||||
if len(o.RetryMode) == 0 {
|
||||
o.RetryMode = aws.RetryModeStandard
|
||||
}
|
||||
|
||||
var standardOptions []func(*retry.StandardOptions)
|
||||
if v := o.RetryMaxAttempts; v != 0 {
|
||||
standardOptions = append(standardOptions, func(so *retry.StandardOptions) {
|
||||
so.MaxAttempts = v
|
||||
})
|
||||
}
|
||||
|
||||
switch o.RetryMode {
|
||||
case aws.RetryModeAdaptive:
|
||||
var adaptiveOptions []func(*retry.AdaptiveModeOptions)
|
||||
if len(standardOptions) != 0 {
|
||||
adaptiveOptions = append(adaptiveOptions, func(ao *retry.AdaptiveModeOptions) {
|
||||
ao.StandardOptions = append(ao.StandardOptions, standardOptions...)
|
||||
})
|
||||
}
|
||||
o.Retryer = retry.NewAdaptiveMode(adaptiveOptions...)
|
||||
|
||||
default:
|
||||
o.Retryer = retry.NewStandard(standardOptions...)
|
||||
}
|
||||
}
|
||||
|
||||
func resolveAWSRetryerProvider(cfg aws.Config, o *Options) {
|
||||
if cfg.Retryer == nil {
|
||||
return
|
||||
}
|
||||
o.Retryer = cfg.Retryer()
|
||||
}
|
||||
|
||||
func resolveAWSRetryMode(cfg aws.Config, o *Options) {
|
||||
if len(cfg.RetryMode) == 0 {
|
||||
return
|
||||
}
|
||||
o.RetryMode = cfg.RetryMode
|
||||
}
|
||||
func resolveAWSRetryMaxAttempts(cfg aws.Config, o *Options) {
|
||||
if cfg.RetryMaxAttempts == 0 {
|
||||
return
|
||||
}
|
||||
o.RetryMaxAttempts = cfg.RetryMaxAttempts
|
||||
}
|
||||
|
||||
func finalizeRetryMaxAttemptOptions(o *Options, client Client) {
|
||||
if v := o.RetryMaxAttempts; v == 0 || v == client.options.RetryMaxAttempts {
|
||||
return
|
||||
}
|
||||
|
||||
o.Retryer = retry.AddWithMaxAttempts(o.Retryer, o.RetryMaxAttempts)
|
||||
}
|
||||
|
||||
func resolveAWSEndpointResolver(cfg aws.Config, o *Options) {
|
||||
if cfg.EndpointResolver == nil && cfg.EndpointResolverWithOptions == nil {
|
||||
return
|
||||
}
|
||||
o.EndpointResolver = withEndpointResolver(cfg.EndpointResolver, cfg.EndpointResolverWithOptions, NewDefaultEndpointResolver())
|
||||
}
|
||||
|
||||
func addClientUserAgent(stack *middleware.Stack) error {
|
||||
return awsmiddleware.AddSDKAgentKeyValue(awsmiddleware.APIMetadata, "ssooidc", goModuleVersion)(stack)
|
||||
}
|
||||
|
||||
func addHTTPSignerV4Middleware(stack *middleware.Stack, o Options) error {
|
||||
mw := v4.NewSignHTTPRequestMiddleware(v4.SignHTTPRequestMiddlewareOptions{
|
||||
CredentialsProvider: o.Credentials,
|
||||
Signer: o.HTTPSignerV4,
|
||||
LogSigning: o.ClientLogMode.IsSigning(),
|
||||
})
|
||||
return stack.Finalize.Add(mw, middleware.After)
|
||||
}
|
||||
|
||||
type HTTPSignerV4 interface {
|
||||
SignHTTP(ctx context.Context, credentials aws.Credentials, r *http.Request, payloadHash string, service string, region string, signingTime time.Time, optFns ...func(*v4.SignerOptions)) error
|
||||
}
|
||||
|
||||
func resolveHTTPSignerV4(o *Options) {
|
||||
if o.HTTPSignerV4 != nil {
|
||||
return
|
||||
}
|
||||
o.HTTPSignerV4 = newDefaultV4Signer(*o)
|
||||
}
|
||||
|
||||
func newDefaultV4Signer(o Options) *v4.Signer {
|
||||
return v4.NewSigner(func(so *v4.SignerOptions) {
|
||||
so.Logger = o.Logger
|
||||
so.LogSigning = o.ClientLogMode.IsSigning()
|
||||
})
|
||||
}
|
||||
|
||||
func addRetryMiddlewares(stack *middleware.Stack, o Options) error {
|
||||
mo := retry.AddRetryMiddlewaresOptions{
|
||||
Retryer: o.Retryer,
|
||||
LogRetryAttempts: o.ClientLogMode.IsRetries(),
|
||||
}
|
||||
return retry.AddRetryMiddlewares(stack, mo)
|
||||
}
|
||||
|
||||
// resolves dual-stack endpoint configuration
|
||||
func resolveUseDualStackEndpoint(cfg aws.Config, o *Options) error {
|
||||
if len(cfg.ConfigSources) == 0 {
|
||||
return nil
|
||||
}
|
||||
value, found, err := internalConfig.ResolveUseDualStackEndpoint(context.Background(), cfg.ConfigSources)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if found {
|
||||
o.EndpointOptions.UseDualStackEndpoint = value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// resolves FIPS endpoint configuration
|
||||
func resolveUseFIPSEndpoint(cfg aws.Config, o *Options) error {
|
||||
if len(cfg.ConfigSources) == 0 {
|
||||
return nil
|
||||
}
|
||||
value, found, err := internalConfig.ResolveUseFIPSEndpoint(context.Background(), cfg.ConfigSources)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if found {
|
||||
o.EndpointOptions.UseFIPSEndpoint = value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addRequestIDRetrieverMiddleware(stack *middleware.Stack) error {
|
||||
return awsmiddleware.AddRequestIDRetrieverMiddleware(stack)
|
||||
}
|
||||
|
||||
func addResponseErrorMiddleware(stack *middleware.Stack) error {
|
||||
return awshttp.AddResponseErrorMiddleware(stack)
|
||||
}
|
||||
|
||||
func addRequestResponseLogging(stack *middleware.Stack, o Options) error {
|
||||
return stack.Deserialize.Add(&smithyhttp.RequestResponseLogger{
|
||||
LogRequest: o.ClientLogMode.IsRequest(),
|
||||
LogRequestWithBody: o.ClientLogMode.IsRequestWithBody(),
|
||||
LogResponse: o.ClientLogMode.IsResponse(),
|
||||
LogResponseWithBody: o.ClientLogMode.IsResponseWithBody(),
|
||||
}, middleware.After)
|
||||
}
|
@ -0,0 +1,179 @@
|
||||
// Code generated by smithy-go-codegen DO NOT EDIT.
|
||||
|
||||
package ssooidc
|
||||
|
||||
import (
|
||||
"context"
|
||||
awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
smithyhttp "github.com/aws/smithy-go/transport/http"
|
||||
)
|
||||
|
||||
// Creates and returns an access token for the authorized client. The access token
|
||||
// issued will be used to fetch short-term credentials for the assigned roles in
|
||||
// the AWS account.
|
||||
func (c *Client) CreateToken(ctx context.Context, params *CreateTokenInput, optFns ...func(*Options)) (*CreateTokenOutput, error) {
|
||||
if params == nil {
|
||||
params = &CreateTokenInput{}
|
||||
}
|
||||
|
||||
result, metadata, err := c.invokeOperation(ctx, "CreateToken", params, optFns, c.addOperationCreateTokenMiddlewares)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := result.(*CreateTokenOutput)
|
||||
out.ResultMetadata = metadata
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type CreateTokenInput struct {
|
||||
|
||||
// The unique identifier string for each client. This value should come from the
|
||||
// persisted result of the RegisterClient API.
|
||||
//
|
||||
// This member is required.
|
||||
ClientId *string
|
||||
|
||||
// A secret string generated for the client. This value should come from the
|
||||
// persisted result of the RegisterClient API.
|
||||
//
|
||||
// This member is required.
|
||||
ClientSecret *string
|
||||
|
||||
// Supports grant types for the authorization code, refresh token, and device code
|
||||
// request. For device code requests, specify the following value:
|
||||
// urn:ietf:params:oauth:grant-type:device_code For information about how to
|
||||
// obtain the device code, see the StartDeviceAuthorization topic.
|
||||
//
|
||||
// This member is required.
|
||||
GrantType *string
|
||||
|
||||
// The authorization code received from the authorization service. This parameter
|
||||
// is required to perform an authorization grant request to get access to a token.
|
||||
Code *string
|
||||
|
||||
// Used only when calling this API for the device code grant type. This short-term
|
||||
// code is used to identify this authentication attempt. This should come from an
|
||||
// in-memory reference to the result of the StartDeviceAuthorization API.
|
||||
DeviceCode *string
|
||||
|
||||
// The location of the application that will receive the authorization code. Users
|
||||
// authorize the service to send the request to this location.
|
||||
RedirectUri *string
|
||||
|
||||
// Currently, refreshToken is not yet implemented and is not supported. For more
|
||||
// information about the features and limitations of the current IAM Identity
|
||||
// Center OIDC implementation, see Considerations for Using this Guide in the IAM
|
||||
// Identity Center OIDC API Reference
|
||||
// (https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/Welcome.html).
|
||||
// The token used to obtain an access token in the event that the access token is
|
||||
// invalid or expired.
|
||||
RefreshToken *string
|
||||
|
||||
// The list of scopes that is defined by the client. Upon authorization, this list
|
||||
// is used to restrict permissions when granting an access token.
|
||||
Scope []string
|
||||
|
||||
noSmithyDocumentSerde
|
||||
}
|
||||
|
||||
type CreateTokenOutput struct {
|
||||
|
||||
// An opaque token to access IAM Identity Center resources assigned to a user.
|
||||
AccessToken *string
|
||||
|
||||
// Indicates the time in seconds when an access token will expire.
|
||||
ExpiresIn int32
|
||||
|
||||
// Currently, idToken is not yet implemented and is not supported. For more
|
||||
// information about the features and limitations of the current IAM Identity
|
||||
// Center OIDC implementation, see Considerations for Using this Guide in the IAM
|
||||
// Identity Center OIDC API Reference
|
||||
// (https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/Welcome.html).
|
||||
// The identifier of the user that associated with the access token, if present.
|
||||
IdToken *string
|
||||
|
||||
// Currently, refreshToken is not yet implemented and is not supported. For more
|
||||
// information about the features and limitations of the current IAM Identity
|
||||
// Center OIDC implementation, see Considerations for Using this Guide in the IAM
|
||||
// Identity Center OIDC API Reference
|
||||
// (https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/Welcome.html).
|
||||
// A token that, if present, can be used to refresh a previously issued access
|
||||
// token that might have expired.
|
||||
RefreshToken *string
|
||||
|
||||
// Used to notify the client that the returned token is an access token. The
|
||||
// supported type is BearerToken.
|
||||
TokenType *string
|
||||
|
||||
// Metadata pertaining to the operation's result.
|
||||
ResultMetadata middleware.Metadata
|
||||
|
||||
noSmithyDocumentSerde
|
||||
}
|
||||
|
||||
func (c *Client) addOperationCreateTokenMiddlewares(stack *middleware.Stack, options Options) (err error) {
|
||||
err = stack.Serialize.Add(&awsRestjson1_serializeOpCreateToken{}, middleware.After)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = stack.Deserialize.Add(&awsRestjson1_deserializeOpCreateToken{}, middleware.After)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addSetLoggerMiddleware(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addResolveEndpointMiddleware(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addRetryMiddlewares(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addClientUserAgent(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addOpCreateTokenValidationMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stack.Initialize.Add(newServiceMetadataMiddleware_opCreateToken(options.Region), middleware.Before); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addRequestIDRetrieverMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addResponseErrorMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addRequestResponseLogging(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newServiceMetadataMiddleware_opCreateToken(region string) *awsmiddleware.RegisterServiceMetadata {
|
||||
return &awsmiddleware.RegisterServiceMetadata{
|
||||
Region: region,
|
||||
ServiceID: ServiceID,
|
||||
OperationName: "CreateToken",
|
||||
}
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
// Code generated by smithy-go-codegen DO NOT EDIT.
|
||||
|
||||
package ssooidc
|
||||
|
||||
import (
|
||||
"context"
|
||||
awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
smithyhttp "github.com/aws/smithy-go/transport/http"
|
||||
)
|
||||
|
||||
// Registers a client with IAM Identity Center. This allows clients to initiate
|
||||
// device authorization. The output should be persisted for reuse through many
|
||||
// authentication requests.
|
||||
func (c *Client) RegisterClient(ctx context.Context, params *RegisterClientInput, optFns ...func(*Options)) (*RegisterClientOutput, error) {
|
||||
if params == nil {
|
||||
params = &RegisterClientInput{}
|
||||
}
|
||||
|
||||
result, metadata, err := c.invokeOperation(ctx, "RegisterClient", params, optFns, c.addOperationRegisterClientMiddlewares)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := result.(*RegisterClientOutput)
|
||||
out.ResultMetadata = metadata
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type RegisterClientInput struct {
|
||||
|
||||
// The friendly name of the client.
|
||||
//
|
||||
// This member is required.
|
||||
ClientName *string
|
||||
|
||||
// The type of client. The service supports only public as a client type. Anything
|
||||
// other than public will be rejected by the service.
|
||||
//
|
||||
// This member is required.
|
||||
ClientType *string
|
||||
|
||||
// The list of scopes that are defined by the client. Upon authorization, this list
|
||||
// is used to restrict permissions when granting an access token.
|
||||
Scopes []string
|
||||
|
||||
noSmithyDocumentSerde
|
||||
}
|
||||
|
||||
type RegisterClientOutput struct {
|
||||
|
||||
// The endpoint where the client can request authorization.
|
||||
AuthorizationEndpoint *string
|
||||
|
||||
// The unique identifier string for each client. This client uses this identifier
|
||||
// to get authenticated by the service in subsequent calls.
|
||||
ClientId *string
|
||||
|
||||
// Indicates the time at which the clientId and clientSecret were issued.
|
||||
ClientIdIssuedAt int64
|
||||
|
||||
// A secret string generated for the client. The client will use this string to get
|
||||
// authenticated by the service in subsequent calls.
|
||||
ClientSecret *string
|
||||
|
||||
// Indicates the time at which the clientId and clientSecret will become invalid.
|
||||
ClientSecretExpiresAt int64
|
||||
|
||||
// The endpoint where the client can get an access token.
|
||||
TokenEndpoint *string
|
||||
|
||||
// Metadata pertaining to the operation's result.
|
||||
ResultMetadata middleware.Metadata
|
||||
|
||||
noSmithyDocumentSerde
|
||||
}
|
||||
|
||||
func (c *Client) addOperationRegisterClientMiddlewares(stack *middleware.Stack, options Options) (err error) {
|
||||
err = stack.Serialize.Add(&awsRestjson1_serializeOpRegisterClient{}, middleware.After)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = stack.Deserialize.Add(&awsRestjson1_deserializeOpRegisterClient{}, middleware.After)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addSetLoggerMiddleware(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addResolveEndpointMiddleware(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addRetryMiddlewares(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addClientUserAgent(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addOpRegisterClientValidationMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stack.Initialize.Add(newServiceMetadataMiddleware_opRegisterClient(options.Region), middleware.Before); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addRequestIDRetrieverMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addResponseErrorMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addRequestResponseLogging(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newServiceMetadataMiddleware_opRegisterClient(region string) *awsmiddleware.RegisterServiceMetadata {
|
||||
return &awsmiddleware.RegisterServiceMetadata{
|
||||
Region: region,
|
||||
ServiceID: ServiceID,
|
||||
OperationName: "RegisterClient",
|
||||
}
|
||||
}
|
150
vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go
generated
vendored
150
vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go
generated
vendored
@ -0,0 +1,150 @@
|
||||
// Code generated by smithy-go-codegen DO NOT EDIT.
|
||||
|
||||
package ssooidc
|
||||
|
||||
import (
|
||||
"context"
|
||||
awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
smithyhttp "github.com/aws/smithy-go/transport/http"
|
||||
)
|
||||
|
||||
// Initiates device authorization by requesting a pair of verification codes from
|
||||
// the authorization service.
|
||||
func (c *Client) StartDeviceAuthorization(ctx context.Context, params *StartDeviceAuthorizationInput, optFns ...func(*Options)) (*StartDeviceAuthorizationOutput, error) {
|
||||
if params == nil {
|
||||
params = &StartDeviceAuthorizationInput{}
|
||||
}
|
||||
|
||||
result, metadata, err := c.invokeOperation(ctx, "StartDeviceAuthorization", params, optFns, c.addOperationStartDeviceAuthorizationMiddlewares)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := result.(*StartDeviceAuthorizationOutput)
|
||||
out.ResultMetadata = metadata
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type StartDeviceAuthorizationInput struct {
|
||||
|
||||
// The unique identifier string for the client that is registered with IAM Identity
|
||||
// Center. This value should come from the persisted result of the RegisterClient
|
||||
// API operation.
|
||||
//
|
||||
// This member is required.
|
||||
ClientId *string
|
||||
|
||||
// A secret string that is generated for the client. This value should come from
|
||||
// the persisted result of the RegisterClient API operation.
|
||||
//
|
||||
// This member is required.
|
||||
ClientSecret *string
|
||||
|
||||
// The URL for the AWS access portal. For more information, see Using the AWS
|
||||
// access portal
|
||||
// (https://docs.aws.amazon.com/singlesignon/latest/userguide/using-the-portal.html)
|
||||
// in the IAM Identity Center User Guide.
|
||||
//
|
||||
// This member is required.
|
||||
StartUrl *string
|
||||
|
||||
noSmithyDocumentSerde
|
||||
}
|
||||
|
||||
type StartDeviceAuthorizationOutput struct {
|
||||
|
||||
// The short-lived code that is used by the device when polling for a session
|
||||
// token.
|
||||
DeviceCode *string
|
||||
|
||||
// Indicates the number of seconds in which the verification code will become
|
||||
// invalid.
|
||||
ExpiresIn int32
|
||||
|
||||
// Indicates the number of seconds the client must wait between attempts when
|
||||
// polling for a session.
|
||||
Interval int32
|
||||
|
||||
// A one-time user verification code. This is needed to authorize an in-use device.
|
||||
UserCode *string
|
||||
|
||||
// The URI of the verification page that takes the userCode to authorize the
|
||||
// device.
|
||||
VerificationUri *string
|
||||
|
||||
// An alternate URL that the client can use to automatically launch a browser. This
|
||||
// process skips the manual step in which the user visits the verification page and
|
||||
// enters their code.
|
||||
VerificationUriComplete *string
|
||||
|
||||
// Metadata pertaining to the operation's result.
|
||||
ResultMetadata middleware.Metadata
|
||||
|
||||
noSmithyDocumentSerde
|
||||
}
|
||||
|
||||
func (c *Client) addOperationStartDeviceAuthorizationMiddlewares(stack *middleware.Stack, options Options) (err error) {
|
||||
err = stack.Serialize.Add(&awsRestjson1_serializeOpStartDeviceAuthorization{}, middleware.After)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = stack.Deserialize.Add(&awsRestjson1_deserializeOpStartDeviceAuthorization{}, middleware.After)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addSetLoggerMiddleware(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addResolveEndpointMiddleware(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addRetryMiddlewares(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addClientUserAgent(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addOpStartDeviceAuthorizationValidationMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stack.Initialize.Add(newServiceMetadataMiddleware_opStartDeviceAuthorization(options.Region), middleware.Before); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addRequestIDRetrieverMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addResponseErrorMiddleware(stack); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addRequestResponseLogging(stack, options); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newServiceMetadataMiddleware_opStartDeviceAuthorization(region string) *awsmiddleware.RegisterServiceMetadata {
|
||||
return &awsmiddleware.RegisterServiceMetadata{
|
||||
Region: region,
|
||||
ServiceID: ServiceID,
|
||||
OperationName: "StartDeviceAuthorization",
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue