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
@ -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",
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue