From df543cd12640be3842239ed7c4caf4a507cebb29 Mon Sep 17 00:00:00 2001 From: Lucas Almeida Date: Sat, 16 Aug 2025 17:21:13 -0300 Subject: [PATCH 1/5] fix: handle unchained credential sources --- vault/vault.go | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/vault/vault.go b/vault/vault.go index 7cec45b1e..b5529dc8b 100644 --- a/vault/vault.go +++ b/vault/vault.go @@ -254,23 +254,10 @@ func (t *TempCredentialsCreator) getSourceCredWithSession(config *ProfileConfig, return nil, err } - if hasStoredCredentials || !config.HasRole() { - if canUse, reason := t.canUseGetSessionToken(config); !canUse { - log.Printf("profile %s: skipping GetSessionToken because %s", config.ProfileName, reason) - if !config.HasRole() { - return sourcecredsProvider, nil - } - } - t.chainedMfa = config.MfaSerial - log.Printf("profile %s: using GetSessionToken %s", config.ProfileName, mfaDetails(false, config)) - sourcecredsProvider, err = NewSessionTokenProvider(sourcecredsProvider, t.Keyring.Keyring, config, !t.DisableCache) - if !config.HasRole() || err != nil { - return sourcecredsProvider, err - } - } + isChainedCredentialSource := config.ChainedFromProfile != nil - if config.HasRole() { - isMfaChained := config.MfaSerial != "" && config.MfaSerial == t.chainedMfa + if config.HasRole() && !isChainedCredentialSource { + isMfaChained := config.SourceProfile != nil && config.MfaSerial == config.SourceProfile.MfaSerial if isMfaChained { config.MfaSerial = "" } @@ -278,7 +265,7 @@ func (t *TempCredentialsCreator) getSourceCredWithSession(config *ProfileConfig, return NewAssumeRoleProvider(sourcecredsProvider, t.Keyring.Keyring, config, !t.DisableCache) } - if isMasterCredentialsProvider(sourcecredsProvider) { + if isMasterCredentialsProvider(sourcecredsProvider) || isChainedCredentialSource { canUseGetSessionToken, reason := t.canUseGetSessionToken(config) if canUseGetSessionToken { t.chainedMfa = config.MfaSerial From 773d7b6b015011e7ad19a24e6bc446cf5194ae16 Mon Sep 17 00:00:00 2001 From: Lucas Almeida Date: Sat, 16 Aug 2025 22:54:32 -0300 Subject: [PATCH 2/5] fix: return if cannot use GetSessionToken in chained methods to avoid prompting source mfa --- vault/vault.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/vault/vault.go b/vault/vault.go index b5529dc8b..13dfa4e53 100644 --- a/vault/vault.go +++ b/vault/vault.go @@ -267,12 +267,13 @@ func (t *TempCredentialsCreator) getSourceCredWithSession(config *ProfileConfig, if isMasterCredentialsProvider(sourcecredsProvider) || isChainedCredentialSource { canUseGetSessionToken, reason := t.canUseGetSessionToken(config) - if canUseGetSessionToken { - t.chainedMfa = config.MfaSerial - log.Printf("profile %s: using GetSessionToken %s", config.ProfileName, mfaDetails(false, config)) - return NewSessionTokenProvider(sourcecredsProvider, t.Keyring.Keyring, config, !t.DisableCache) + if !canUseGetSessionToken { + log.Printf("profile %s: skipping GetSessionToken because %s", config.ProfileName, reason) + return sourcecredsProvider, nil } - log.Printf("profile %s: skipping GetSessionToken because %s", config.ProfileName, reason) + t.chainedMfa = config.MfaSerial + log.Printf("profile %s: using GetSessionToken %s", config.ProfileName, mfaDetails(false, config)) + return NewSessionTokenProvider(sourcecredsProvider, t.Keyring.Keyring, config, !t.DisableCache) } return sourcecredsProvider, nil From efc36b8035be7b978070ccb141ac65b29ce16aea Mon Sep 17 00:00:00 2001 From: Lucas Almeida Date: Sat, 16 Aug 2025 23:06:02 -0300 Subject: [PATCH 3/5] style: reverting to the original way to verify if is chainedMfa --- vault/vault.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vault/vault.go b/vault/vault.go index 13dfa4e53..450fea591 100644 --- a/vault/vault.go +++ b/vault/vault.go @@ -257,7 +257,7 @@ func (t *TempCredentialsCreator) getSourceCredWithSession(config *ProfileConfig, isChainedCredentialSource := config.ChainedFromProfile != nil if config.HasRole() && !isChainedCredentialSource { - isMfaChained := config.SourceProfile != nil && config.MfaSerial == config.SourceProfile.MfaSerial + isMfaChained := config.MfaSerial != "" && config.MfaSerial == t.chainedMfa if isMfaChained { config.MfaSerial = "" } From 8bd1b671f9cca9f2eb1b7a0c6dbba173a22ae810 Mon Sep 17 00:00:00 2001 From: Lucas Almeida Date: Sat, 16 Aug 2025 23:41:37 -0300 Subject: [PATCH 4/5] merge: from ByteNess/aws-vault, resolving conflits --- .github/CODEOWNERS | 1 + .github/CODE_OF_CONDUCT.md | 132 +++++++++++++++ .github/CONTRIBUTING.md | 71 ++++++++ .github/dependabot.yml | 11 ++ .github/labeler.yml | 11 ++ .github/release.yml | 30 ++++ .github/workflows/go.yml | 39 +++-- .github/workflows/pr.yaml | 31 ++++ .github/workflows/release.yaml | 111 ++++++++++++ .github/workflows/stale.yml | 2 +- .gitignore | 27 +++ .golangci.yml => .golangci.yaml | 12 +- .goreleaser.yaml | 122 +++++++++++++ LICENSE | 2 +- Makefile | 44 ++++- README.md | 43 +++-- SECURITY.md | 22 +++ USAGE.md | 68 ++++++-- bin/create-dmg | 2 +- cli/add.go | 6 +- cli/clear.go | 4 +- cli/exec.go | 21 ++- cli/exec_test.go | 2 +- cli/export.go | 19 ++- cli/export_test.go | 2 +- cli/global.go | 64 ++++++- cli/list.go | 4 +- cli/list_test.go | 2 +- cli/login.go | 58 ++++++- cli/proxy.go | 2 +- cli/remove.go | 6 +- cli/rotate.go | 22 ++- contrib/completions/zsh/aws-vault.zsh | 34 ++-- contrib/docker/Dockerfile | 2 +- go.mod | 86 +++++++--- go.sum | 235 +++++++++++++++++++------- main.go | 2 +- server/ec2alias_windows.go | 3 + server/ec2server.go | 6 +- server/ecsserver.go | 4 +- vault/config_test.go | 2 +- vault/credentialkeyring.go | 2 +- vault/mfa.go | 16 +- vault/mfa_unix.go | 23 +++ vault/mfa_windows.go | 28 +++ vault/oidctokenkeyring.go | 2 +- vault/sessionkeyring.go | 2 +- vault/sessionkeyring_test.go | 2 +- vault/ssorolecredentialsprovider.go | 2 +- vault/vault.go | 2 +- vault/vault_test.go | 4 +- 51 files changed, 1221 insertions(+), 229 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .github/CODE_OF_CONDUCT.md create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/dependabot.yml create mode 100644 .github/labeler.yml create mode 100644 .github/release.yml create mode 100644 .github/workflows/pr.yaml create mode 100644 .github/workflows/release.yaml rename .golangci.yml => .golangci.yaml (73%) create mode 100644 .goreleaser.yaml create mode 100644 SECURITY.md create mode 100644 vault/mfa_unix.go create mode 100644 vault/mfa_windows.go diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..b65e8daea --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @mbevc1 diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..111f191da --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[INSERT CONTACT METHOD]. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available +at [https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..0729657c1 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,71 @@ +# Contributing + +## Issues + +Issues are very valuable to this project. + +* Ideas are a valuable source of contributions others can make +* Problems show where this project is lacking +* With a question you show where contributors can improve the user experience + +Thank you for creating them. + +Please use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) and subjects for easier classification. + +## Pull Requests + +Pull requests are, a great way to get your ideas into this repository. + +Please use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) and subjects for easier classification. + +When deciding if I merge in a pull request I look at the following things: + +### Does it state intent + +You should be clear which problem you're trying to solve with your contribution. + +For example: + +> Add link to code of conduct in README.md + +Doesn't tell me anything about why you're doing that + +> Add link to code of conduct in README.md because users don't always look in the CONTRIBUTING.md + +Tells me the problem that you have found, and the pull request shows me the action you have taken to solve it. + +### Is it of good quality + +* There are no spelling mistakes +* It reads well +* For english language contributions: Has a good score on [Grammarly](https://www.grammarly.com) or [Hemingway App](http://www.hemingwayapp.com/) + +### Does it move this repository closer to vision for the repository + +The aim of this repository is: + +* To provide a README.md and assorted documents anyone can copy and paste, into their project +* The content is usable by someone who hasn't written something like this before +* Foster a culture of respect and gratitude in the open source community. + +### Does it follow the contributor covenant + +This repository has a [code of conduct](CODE_OF_CONDUCT.md), This repository has a code of conduct, I will remove things that do not respect it. + +## Development + +### Linting + +We use `go vet` and `golangci-lint` in order to maintain a good code quality and a consistent style. + +Get the `golangci-lint` by following their installation instructions on [golangci-lint.run](https://golangci-lint.run/) or simply run: + +```shell +bin install github.com/golangci/golangci-lint +``` + +Lint the source code by executing: + +```shell +golangci-lint run ./... +``` diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..cd885540d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "gomod" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 000000000..fe3cb6ef6 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,11 @@ +documentation: + - changed-files: + - any-glob-to-any-file: '*.md' + +dependencies: + - changed-files: + - any-glob-to-any-file: 'go.*' + +pipelines: + - changed-files: + - any-glob-to-any-file: '.github/**' diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 000000000..88dbbe4ac --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,30 @@ +changelog: + exclude: + labels: + - ignore-for-release + authors: + - octocat + categories: + - title: Breaking Changes πŸ›  + labels: + - Semver-Major + - breaking-change + - title: Exciting New Features πŸŽ‰ + labels: + - Semver-Minor + - enhancement + - feat + - title: Bug fixes πŸ› + labels: + - bug + - fix + - title: Documentation changes πŸ“ + labels: + - documentation + - docs + - title: Dependencies πŸ‘’ + labels: + - dependencies + - title: Other Changes 🎯 + labels: + - "*" diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 6018f7c35..5a36d23ad 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -1,12 +1,21 @@ name: Continuous Integration on: push: + branches-ignore: + - main + paths-ignore: + - '.github/**' + - '.gitgnore' pull_request: branches: - - master + - main permissions: contents: read +env: + GOTELEMETRY: off + #CGO_ENABLED: 0 + jobs: test: name: test @@ -15,12 +24,14 @@ jobs: os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/setup-go@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' - - uses: actions/checkout@v3 + #go-version: '1.20' + go-version-file: 'go.mod' + check-latest: true - name: Run tests - run: go test -race ./... + run: make test #go test -race ./... lint: permissions: contents: read # for actions/checkout to fetch code @@ -31,11 +42,15 @@ jobs: os: [macos-latest, ubuntu-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/setup-go@v3 - with: - go-version: '1.20' - - uses: actions/checkout@v3 - - name: golangci-lint - uses: golangci/golangci-lint-action@v3.4.0 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: - version: v1.52.0 + #go-version: '1.20' + go-version-file: 'go.mod' + check-latest: true + - name: Lint + run: make vet + #- name: golangci-lint + # uses: golangci/golangci-lint-action@v8 + # with: + # version: v2.1 diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 000000000..dd61a3cab --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,31 @@ +name: PR checks + +on: + pull_request: + types: [opened, synchronize, reopened, edited] + +permissions: + contents: read # This is required for the label PR action + pull-requests: write # This is required for the label PR action + +jobs: + validate-pr-title: + name: Validate PR + runs-on: ubuntu-latest + steps: + - name: PR Conventional Commit Validation + uses: ytanikin/pr-conventional-commits@1.4.1 + with: + task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]' + add_label: 'true' + #custom_labels: '{"feat": "feature", "fix": "fix", "docs": "documentation", "test": "test", "ci": "CI/CD", "refactor": "refactor", "perf": "performance", "chore": "chore", "revert": "revert", "wip": "WIP"}' + #add_scope_label: 'true' + labeler: + name: Label PRs + runs-on: ubuntu-latest + steps: + - name: Label PRs + id: label-prs + uses: actions/labeler@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 000000000..a24cabe92 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,111 @@ +on: + push: + tags: + - 'v*' + #tag-ignore: + # - 'v*' + workflow_dispatch: {} + +env: + GOTELEMETRY: off + CGO_ENABLED: 0 + +permissions: + contents: write + +name: Build & Release +jobs: + build: + if: startsWith(github.ref, 'refs/tags/v') + name: Build + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + #needs: [ test ] + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # disable shallow clone - get all + + #- name: Unshallow + # run: git fetch --prune --unshallow + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + check-latest: true + id: go + + - name: Generate build tag + run: | + VERSION=$(git describe --tags --always --dirty --match=v* 2> /dev/null || echo v0) + echo "VERSION=$VERSION" >> $GITHUB_ENV + shell: /bin/bash -e {0} + + - name: Build artefacts + run: | + echo "${VERSION} on ${{ matrix.os }}" + make ${{ matrix.os }} + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: aws-vault-${{ matrix.os }} + retention-days: 7 + path: ./aws-vault-* + + release: + name: Release + needs: build + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install UPX + run: sudo apt-get update && sudo apt-get install -y upx + + - name: Download Artifacts + uses: actions/download-artifact@v4 + with: + path: dist + merge-multiple: true + + # NOTE: Disabled for {windows-amd64} due Chocolately AV false positives + - name: Compress binaries with UPX + run: | + chmod +x dist/aws-vault-* + upx dist/aws-vault-linux* + + - name: Generate SHA256 checksums + run: | + cp dist/aws-vault-* . + make aws-vault_sha256_checksums.txt + cp aws-vault_sha256_checksums.txt dist/ + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + # Identify if this is a pre release by checking if the tag name contains -rc, -b, -a + prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-b') || contains(github.ref, '-a') }} + files: | + dist/** + tag_name: ${{ github.ref_name }} + generate_release_notes: true + #body: "Changelog of release ${{ github.ref_name }}." + #append_body: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + #- name: Run GoReleaser + # uses: goreleaser/goreleaser-action@v6 + # with: + # version: '~> v2' # latest + # args: release --clean + # workdir: . + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # VERSION: ${{ env.VERSION }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f1c293299..3e2ae22c7 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -9,7 +9,7 @@ jobs: permissions: issues: write steps: - - uses: actions/stale@v7 + - uses: actions/stale@v9 with: days-before-stale: 180 days-before-close: 7 diff --git a/.gitignore b/.gitignore index 359f9e9fd..ea5fe79f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,30 @@ /aws-vault /aws-vault-* /SHA256SUMS + +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work +go.work.sum + +# env file +.env + +build/ +dist/ +vendor/ diff --git a/.golangci.yml b/.golangci.yaml similarity index 73% rename from .golangci.yml rename to .golangci.yaml index 20f3f8bc4..5c57ea3c2 100644 --- a/.golangci.yml +++ b/.golangci.yaml @@ -1,4 +1,12 @@ +version: "2" linters: + settings: + depguard: + rules: + main: + list-mode: lax + files: + - $all enable: - bodyclose - contextcheck @@ -8,9 +16,7 @@ linters: - errchkjson - errname - exhaustive - - exportloopref - - gofmt - - goimports + - govet - makezero - misspell - nakedret diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 000000000..4efbcc1d4 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,122 @@ +version: 2 +project_name: aws-vault + +source: + enabled: false + +env: + #- GO111MODULE=on + #- GOPROXY=https://gocenter.io + +#before: +# hooks: +# - go mod tidy +# - go mod vendor +# #- go mod download + +builds: + - binary: aws-vault + #main: ./main.go + #goos: + # - linux + # - darwin + # - windows + #goarch: + # - amd64 + targets: + - linux_amd64 + - windows_amd64 + - darwin_amd64 + - darwin_arm64 + env: + - CGO_ENABLED=1 + - GOTELEMETRY="off" + flags: + - -v + ldflags: + - -s -w -X main.Version={{.Version}} + +upx: + - enabled: true + #goos: [linux, windows] + +archives: + - id: aws-vault + #builds: + # - aws-vault|default + #format: zip + #name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}" + format_overrides: + - goos: windows + formats: ["zip"] + #replacements: + # darwin: Darwin + # linux: Linux + # windows: Windows + #format: tar.gz + #format_overrides: + # - goos: windows + # format: zip + files: + - none* + +universal_binaries: + - replace: true + +release: + prerelease: auto + draft: false + disable: false + name_template: "v{{ .Version }}" + footer: | + **Full Changelog**: https://github.com/byteness/aws-vault/compare/{{ .PreviousTag }}...{{ if .IsNightly }}nightly{{ else }}{{ .Tag }}{{ end }} + +milestones: + - close: true + +checksum: + name_template: "{{ .ProjectName }}_{{ .Version }}_sha256_checksums.txt" + algorithm: sha256 + +changelog: + use: github #git # github(-native) + sort: asc + format: "{{ .SHA }}: {{ .Message }}{{ with .AuthorUsername }} (@{{ . }}){{ end }}" + # Disabled when using 'github-native'. + groups: + - title: "πŸš€ New Features" + regexp: '^.*?feat(\(.+\))??!?:.+$' + #regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$' + order: 100 + - title: "πŸ”’ Security updates" + regexp: '^.*?sec(\(.+\))??!?:.+$' + order: 150 + - title: "πŸ› Bug fixes" + regexp: '^.*?(fix|refactor|bug)(\(.+\))??!?:.+$' + # regexp: '^.*?(fix|bug)(\([[:word:]]+\))??!?:.+$' + order: 200 + - title: "πŸ“ Documentation updates" + regexp: ^.*?docs?(\(.+\))??!?:.+$ + order: 400 + - title: 🎯 Other work + order: 9999 + filters: + exclude: + - "^test:" + - "^test\\(" + - "^chore: update$" + - "^chore: docs$" + - "^docs: update$" + - "^chore: schema$" + - "^chore: typo$" + - "^chore: auto-update generated files$" + - "^chore: update schema$" + - "^chore: schema update$" + - "^chore\\(deps\\): " + - "^(build|ci): " + - "merge conflict" + - "merge conflict" + - Merge pull request + - Merge remote-tracking branch + - Merge branch + - typo diff --git a/LICENSE b/LICENSE index 0fe9e4692..d7813814e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 99designs +Copyright (c) 2015 ByteNess Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index 976f4bd13..c0df0a5b4 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,17 @@ VERSION=$(shell git describe --tags --candidates=1 --dirty) -BUILD_FLAGS=-ldflags="-X main.Version=$(VERSION)" -trimpath -CERT_ID ?= Developer ID Application: 99designs Inc (NRM9HVJ62Z) +BUILD_FLAGS=-ldflags="-s -w -X main.Version=$(VERSION)" -trimpath +CERT_ID ?= Developer ID Application: ByteNess (R) SRC=$(shell find . -name '*.go') go.mod INSTALL_DIR ?= ~/bin -.PHONY: binaries clean release install +.PHONY: binaries clean release install snapshot run ifeq ($(shell uname), Darwin) aws-vault: $(SRC) - go build -ldflags="-X main.Version=$(VERSION)" -o $@ . + go build -ldflags="-s -w -X main.Version=$(VERSION)" -o $@ . codesign --options runtime --timestamp --sign "$(CERT_ID)" $@ else aws-vault: $(SRC) - go build -ldflags="-X main.Version=$(VERSION)" -o $@ . + go build -ldflags="-s -w -X main.Version=$(VERSION)" -o $@ . endif install: aws-vault @@ -23,9 +23,27 @@ binaries: aws-vault-linux-amd64 aws-vault-linux-arm64 aws-vault-linux-ppc64le aw dmgs: aws-vault-darwin-amd64.dmg aws-vault-darwin-arm64.dmg clean: - rm -f ./aws-vault ./aws-vault-*-* ./SHA256SUMS + rm -rf ./aws-vault ./aws-vault-*-* ./SHA256SUMS dist/ -release: binaries dmgs SHA256SUMS +snapshot: clean ## Build local snapshot + goreleaser build --clean --snapshot --single-target + +run: + go run . + +test: ## Run tests + go test -v ./... + +fmt: **/*.go ## Formt Golang code + go fmt ./... + +lint: + golint ./... + +vet: + go vet -all ./... + +release: binaries SHA256SUMS @echo "\nTo create a new release run:\n\n gh release create --title $(VERSION) $(VERSION) \ aws-vault-darwin-amd64.dmg \ @@ -41,6 +59,10 @@ release: binaries dmgs SHA256SUMS @echo "\nTo update homebrew-cask run:\n\n brew bump-cask-pr --version $(shell echo $(VERSION) | sed 's/v\(.*\)/\1/') aws-vault\n" +ubuntu-latest: aws-vault-linux-amd64 aws-vault-linux-arm64 aws-vault-windows-amd64.exe aws-vault-windows-arm64.exe aws-vault-freebsd-amd64 + +macos-latest: aws-vault-darwin-amd64 aws-vault-darwin-arm64 + aws-vault-darwin-amd64: $(SRC) GOOS=darwin GOARCH=amd64 CGO_ENABLED=1 SDKROOT=$(shell xcrun --sdk macosx --show-sdk-path) go build $(BUILD_FLAGS) -o $@ . @@ -65,6 +87,9 @@ aws-vault-linux-arm7: $(SRC) aws-vault-windows-386.exe: $(SRC) GOOS=windows GOARCH=386 go build $(BUILD_FLAGS) -o $@ . +aws-vault-windows-amd64.exe: $(SRC) + GOOS=windows GOARCH=amd64 go build $(BUILD_FLAGS) -o $@ . + aws-vault-windows-arm64.exe: $(SRC) GOOS=windows GOARCH=arm64 go build $(BUILD_FLAGS) -o $@ . @@ -74,6 +99,11 @@ aws-vault-darwin-amd64.dmg: aws-vault-darwin-amd64 aws-vault-darwin-arm64.dmg: aws-vault-darwin-arm64 ./bin/create-dmg aws-vault-darwin-arm64 $@ +aws-vault_sha256_checksums.txt: + sha256sum \ + aws-vault-* \ + > $@ + SHA256SUMS: binaries dmgs shasum -a 256 \ aws-vault-darwin-amd64.dmg \ diff --git a/README.md b/README.md index 7066a6f16..059b3b410 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ # AWS Vault -[![Downloads](https://img.shields.io/github/downloads/99designs/aws-vault/total.svg)](https://github.com/99designs/aws-vault/releases) -[![Continuous Integration](https://github.com/99designs/aws-vault/workflows/Continuous%20Integration/badge.svg)](https://github.com/99designs/aws-vault/actions) +[![Downloads](https://img.shields.io/github/downloads/byteness/aws-vault/total)](https://github.com/byteness/aws-vault/releases) +[![Continuous Integration](https://github.com/byteness/aws-vault/workflows/Continuous%20Integration/badge.svg)](https://github.com/byteness/aws-vault/actions) + +> [!NOTE] +> This is a maintained fork of https://github.com/99designs/aws-vault which seems to be an abandoned project. +> Contributions are welcome, but keep in mind this is a side project and maintained on best effort basis! AWS Vault is a tool to securely store and access AWS credentials in a development environment. @@ -12,18 +16,9 @@ Check out the [announcement blog post](https://99designs.com.au/tech-blog/blog/2 ## Installing You can install AWS Vault: -- by downloading the [latest release](https://github.com/99designs/aws-vault/releases/latest) -- on macOS with [Homebrew Cask](https://formulae.brew.sh/cask/aws-vault): `brew install --cask aws-vault` -- on macOS with [MacPorts](https://ports.macports.org/port/aws-vault/summary): `port install aws-vault` -- on Windows with [Chocolatey](https://chocolatey.org/packages/aws-vault): `choco install aws-vault` -- on Windows with [Scoop](https://scoop.sh/): `scoop install aws-vault` -- on Linux with [Homebrew on Linux](https://formulae.brew.sh/formula/aws-vault): `brew install aws-vault` -- on [Arch Linux](https://www.archlinux.org/packages/community/x86_64/aws-vault/): `pacman -S aws-vault` -- on [Gentoo Linux](https://github.com/gentoo/guru/tree/master/app-admin/aws-vault): `emerge --ask app-admin/aws-vault` ([enable Guru first](https://wiki.gentoo.org/wiki/Project:GURU/Information_for_End_Users)) -- on [FreeBSD](https://www.freshports.org/security/aws-vault/): `pkg install aws-vault` -- on [OpenSUSE](https://software.opensuse.org/package/aws-vault): enable devel:languages:go repo then `zypper install aws-vault` -- with [Nix](https://search.nixos.org/packages?show=aws-vault&query=aws-vault): `nix-env -i aws-vault` -- with [asdf-vm](https://github.com/karancode/asdf-aws-vault): `asdf plugin-add aws-vault https://github.com/karancode/asdf-aws-vault.git && asdf install aws-vault ` +- by downloading the [latest release](https://github.com/byteness/aws-vault/releases/latest) +- using [Homebrew](https://formulae.brew.sh/formula/aws-vault): `brew install aws-vault` +- on Windows with [Chocolatey](https://chocolatey.org/packages/aws-vault): `choco install aws-vault` ([repo](https://github.com/gusztavvargadr/aws-vault-chocolatey) by [GusztΓ‘v Varga](https://github.com/gusztavvargadr)) ## Documentation @@ -148,9 +143,15 @@ Here's what you can expect from aws-vault | `aws-vault exec bar-role2` | session-token + role + role | session-token | Yes | | `aws-vault exec bar-role2 --no-session` | role + role | role | Yes | +## Auto-logout + +Since v7.3+ `aws-vault` introduced option to automatically try and do a logout first, before login when executing `aws-vault login `. + +This behavour can be achieved by using `--auto-logout` or `-a` flag! Read more in [USAGE.md](./USAGE.md) file. + ## Development -The [macOS release builds](https://github.com/99designs/aws-vault/releases) are code-signed to avoid extra prompts in Keychain. You can verify this with: +The [macOS release builds](https://github.com/byteness/aws-vault/releases) are code-signed to avoid extra prompts in Keychain. You can verify this with: ```shell $ codesign --verify --verbose $(which aws-vault) ``` @@ -161,6 +162,18 @@ $ go build . $ codesign --sign ./aws-vault ``` +## 🧰 Contributing + +Report issues/questions/feature requests on in the [issues](https://github.com/byteness/aws-vault/issues/new) section. + +Full contributing [guidelines are covered here](.github/CONTRIBUTING.md). + +## Maintainers + +* [Marko Bevc](https://github.com/mbevc1) +* Full [contributors list](https://github.com/byteness/aws-vault/graphs/contributors) + + ## References and Inspiration * https://github.com/pda/aws-keychain diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..eebd47637 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,22 @@ +# Security Policy + +This security policy applies to public projects under the [ByteNess organization][gh-organization] on GitHub. + +## Security/Bugfix Versions + +Security and bug fixes are generally provided only for the last minor version. +Fixes are released either as part of the next minor version or as an on-demand patch version. + +Security fixes are given priority and might be enough to cause a new version to be released. + +## Reporting a Vulnerability + +We encourage responsible disclosure of security vulnerabilities. +If you find something suspicious, we encourage and appreciate your report! + +### Ways to report + +In order for the vulnerability reports to reach maintainers as soon as possible, the preferred way is to use the "Report a vulnerability" button under the "Security" tab of the associated GitHub project. +This creates a private communication channel between the reporter and the maintainers. + +[gh-organization]: https://github.com/ByteNess diff --git a/USAGE.md b/USAGE.md index 3219ad94c..16815c59b 100644 --- a/USAGE.md +++ b/USAGE.md @@ -34,6 +34,7 @@ - [MFA](#mfa) - [Gotchas with MFA config](#gotchas-with-mfa-config) - [Single Sign On (SSO)](#single-sign-on-sso) + - [Assuming a role with SSO](#assuming-a-role-with-sso) - [Assuming roles with web identities](#assuming-roles-with-web-identities) - [Using `credential_process`](#using-credential_process) - [Invoking `aws-vault` via `credential_process`](#invoking-aws-vault-via-credential_process) @@ -272,6 +273,7 @@ WARNING: Use of this option runs against security best practices. It is recommen To configure the default flag values of `aws-vault` and its subcommands: * `AWS_VAULT_BACKEND`: Secret backend to use (see the flag `--backend`) * `AWS_VAULT_KEYCHAIN_NAME`: Name of macOS keychain to use (see the flag `--keychain`) +* `AWS_VAULT_AUTO_LOGOUT`: Enable auto-logout when doing `login` (see the flag `--auto-logout`) * `AWS_VAULT_PROMPT`: Prompt driver to use (see the flag `--prompt`) * `AWS_VAULT_PASS_PASSWORD_STORE_DIR`: Pass password store directory (see the flag `--pass-dir`) * `AWS_VAULT_PASS_CMD`: Name of the pass executable (see the flag `--pass-cmd`) @@ -416,6 +418,8 @@ The minimal IAM policy required to rotate your own credentials is: } ``` +> [!TIP] +> If you omit AWS profile name `aws-vault` will ask you to select from the list of configured profiles in AWS config - similar to when logging into AWS Console. ## Managing Sessions @@ -431,14 +435,22 @@ Using `--` signifies the end of the `aws-vault` options, and allows the shell au If you use `exec` without specifying a command, AWS Vault will create a new interactive subshell. Note that when creating an interactive subshell, bash, zsh and other POSIX shells will execute the `~/.bashrc` or `~/.zshrc` file. If you have local variables, functions or aliases (for example your `PS1` prompt), ensure that they are defined in the rc file so they get executed when the subshell begins. -### Logging into AWS console +> [!TIP] +> If you omit AWS profile name `aws-vault` will ask you to select from the list of configured profiles in AWS config - similar to when logging into AWS Console. +> This only works when spawning a new shell and not when running commands using `--` ! -You can use the `aws-vault login` command to open a browser window and login to AWS Console for a given account: +### Logging into AWS Console + +You can use the `aws-vault login` command to open a browser window and login to AWS Console for a given profile/account: ```shell -$ aws-vault login work +$ aws-vault login myprofile ``` -If you have credentials already available in your environment, aws-vault will use these credentials to sign you in to the AWS console. +> [!NOTE] +> When using multi-session support in AWS Management Console you might need to avoid using auto-logout using `--auto-logout` or `-a`. +> Otherwise URL redirect won't work and you'll end up with HTTP/400 response. + +If you have credentials already available in your environment, `aws-vault` will use these credentials to sign you in to the AWS console. ```shell $ export AWS_ACCESS_KEY_ID=%%% @@ -447,6 +459,17 @@ $ export AWS_SESSION_TOKEN=%%% $ aws-vault login ``` +> [!TIP] +> If you omit AWS profile name and don't have any credentials already available in your environment, `aws-vault` will ask you to select from the list of configured profiles in AWS config. + +```shell +? Choose AWS profile: [Use arrows to move, type to filter] +> default + work + test + sandbox +``` + ### Removing stored sessions If you want to remove sessions managed by `aws-vault` before they expire, you can do this with `aws-vault clear` command. @@ -574,7 +597,7 @@ If your organization uses [AWS IAM Identity Center](https://aws.amazon.com/iam/i * `sso_account_id` The AWS account ID that contains the IAM role that you want to use with this profile. * `sso_role_name` The name of the Identity Center Permission Group that defines the user's permissions when using this profile. -Here is an example configuration using AWS IAM Identity Center for single sign on. +Here is an example configuration using AWS IAM Identity Center for single sign on: ```ini [profile Administrator-123456789012] @@ -584,6 +607,22 @@ sso_account_id=123456789012 sso_role_name=Administrator ``` +### Assuming a role with SSO + +If your SSO Permission Set allows you to assume another IAM role (other than the IAM role auto-generated by your permission set), you can do that by using the `source_profile` option. Here's an example: + +```ini +[profile Administrator-123456789012] +sso_start_url=https://aws-sso-portal.awsapps.com/start +sso_region=eu-west-1 +sso_account_id=123456789012 +sso_role_name=Administrator + +[profile AnotherRole-123456789013] +role_arn=arn:aws:iam::123456789013:role/AnotherRole +source_profile=Administrator-123456789012] +``` + ## Assuming roles with web identities AWS supports assuming roles using [web identity federation and OpenID Connect](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html#cli-configure-role-oidc), including login using Amazon, Google, Facebook or any other OpenID Connect server. The configuration options are as follows: @@ -649,20 +688,21 @@ Yubikeys can be used with AWS Vault via Yubikey's OATH-TOTP support. TOTP is nec ### Prerequisites 1. [A Yubikey that supports OATH-TOTP](https://support.yubico.com/support/solutions/articles/15000006419-using-your-yubikey-with-authenticator-codes) - 2. `ykman`, the [YubiKey Manager CLI](https://github.com/Yubico/yubikey-manager) tool. + 1. `ykman`, the [YubiKey Manager CLI](https://github.com/Yubico/yubikey-manager) tool. You can verify these prerequisites by running `ykman info` and checking `OATH` is enabled. ### Setup - 1. Log into the AWS web console with your IAM user credentials, and navigate to _My Security Credentials_ - 2. Under _Multi-factor authentication (MFA)_, click `Manage MFA device` and add a Virtual MFA device - 3. Instead of showing the QR code, click on `Show secret key` and copy the key. - 4. On a command line, run: + 1. Log into the AWS Management Console with your IAM user credentials, and navigate to IAM, Users and pick your user. + 1. Select the tab _Security Credentials_. + 1. Under _Multi-factor authentication (MFA)_, click `Assign MFA device` and add a _Authenticator app_ MFA device. + 1. Instead of showing the QR code, click on `Show secret key` and copy the key. + 1. On a command line, run: ```shell ykman oath accounts add -t arn:aws:iam::${ACCOUNT_ID}:mfa/${MFA_DEVICE_NAME} ``` replacing `${ACCOUNT_ID}` with your AWS account ID and `${MFA_DEVICE_NAME}` with the name you gave to the MFA device. It will prompt you for a base32 text and you can input the key from step 3. Notice the above command uses `-t` which requires you to touch your YubiKey to generate authentication codes. - 5. Now you have to enter two consecutive MFA codes into the AWS website to assign your key to your AWS login. Just run `ykman oath accounts code arn:aws:iam::${ACCOUNT_ID}:mfa/${MFA_DEVICE_NAME}` to get an authentication code. The codes are re-generated every 30 seconds, so you have to run this command twice with about 30 seconds in between to get two distinct codes. Enter the two codes in the AWS form and click `Assign MFA`. + 1. Now you have to enter two consecutive MFA codes into the AWS website to assign your key to your AWS login. Just run `ykman oath accounts code arn:aws:iam::${ACCOUNT_ID}:mfa/${MFA_DEVICE_NAME}` to get an authentication code. The codes are re-generated every 30 seconds, so you have to run this command twice with about 30 seconds in between to get two distinct codes. Enter the two codes in the AWS form and click `Assign MFA`. A script can be found at [contrib/scripts/aws-iam-create-yubikey-mfa.sh](contrib/scripts/aws-iam-create-yubikey-mfa.sh) to automate the process. Note that this script requires your `$MFA_DEVICE_NAME` to be your IAM username as the `aws iam enable-mfa-device` command in the CLI does not yet offer specifying the name. When only one MFA device was allowed per IAM user, the `$MFA_DEVICE_NAME` would always be your IAM username. @@ -695,9 +735,9 @@ Further config: ## Shell completion You can generate shell completions for - - bash: `eval "$(curl -fs https://raw.githubusercontent.com/99designs/aws-vault/master/contrib/completions/bash/aws-vault.bash)"` - - zsh: `eval "$(curl -fs https://raw.githubusercontent.com/99designs/aws-vault/master/contrib/completions/zsh/aws-vault.zsh)"` - - fish: `eval "$(curl -fs https://raw.githubusercontent.com/99designs/aws-vault/master/contrib/completions/fish/aws-vault.fish)"` + - bash: `eval "$(curl -fs https://raw.githubusercontent.com/byteness/aws-vault/master/contrib/completions/bash/aws-vault.bash)"` + - zsh: `eval "$(curl -fs https://raw.githubusercontent.com/byteness/aws-vault/master/contrib/completions/zsh/aws-vault.zsh)"` + - fish: `eval "$(curl -fs https://raw.githubusercontent.com/byteness/aws-vault/master/contrib/completions/fish/aws-vault.fish)"` Find the completion scripts at [contrib/completions](contrib/completions). diff --git a/bin/create-dmg b/bin/create-dmg index 96c2c2e57..0b61c97e3 100755 --- a/bin/create-dmg +++ b/bin/create-dmg @@ -16,7 +16,7 @@ set -euo pipefail BIN_PATH="$1" DMG_PATH="${2:-$1.dmg}" -CERT_ID="${CERT_ID:-"Developer ID Application: 99designs Inc (NRM9HVJ62Z)"}" +CERT_ID="${CERT_ID:-"Developer ID Application: ByteNess Inc (R)"}" KEYCHAIN_PROFILE="${KEYCHAIN_PROFILE:-AC_PASSWORD}" if [[ -f "$DMG_PATH" ]] ; then diff --git a/cli/add.go b/cli/add.go index cf585edcb..af68db83c 100644 --- a/cli/add.go +++ b/cli/add.go @@ -5,11 +5,11 @@ import ( "log" "os" - "github.com/99designs/aws-vault/v7/prompt" - "github.com/99designs/aws-vault/v7/vault" - "github.com/99designs/keyring" + "github.com/byteness/keyring" "github.com/alecthomas/kingpin/v2" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/byteness/aws-vault/v7/prompt" + "github.com/byteness/aws-vault/v7/vault" ) type AddCommandInput struct { diff --git a/cli/clear.go b/cli/clear.go index c62988fb7..f994164d9 100644 --- a/cli/clear.go +++ b/cli/clear.go @@ -3,9 +3,9 @@ package cli import ( "fmt" - "github.com/99designs/aws-vault/v7/vault" - "github.com/99designs/keyring" + "github.com/byteness/keyring" "github.com/alecthomas/kingpin/v2" + "github.com/byteness/aws-vault/v7/vault" ) type ClearCommandInput struct { diff --git a/cli/exec.go b/cli/exec.go index 47f7f4c54..f9d8f5964 100644 --- a/cli/exec.go +++ b/cli/exec.go @@ -13,12 +13,12 @@ import ( "syscall" "time" - "github.com/99designs/aws-vault/v7/iso8601" - "github.com/99designs/aws-vault/v7/server" - "github.com/99designs/aws-vault/v7/vault" - "github.com/99designs/keyring" "github.com/alecthomas/kingpin/v2" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/byteness/aws-vault/v7/iso8601" + "github.com/byteness/aws-vault/v7/server" + "github.com/byteness/aws-vault/v7/vault" + "github.com/byteness/keyring" ) type ExecCommandInput struct { @@ -108,7 +108,7 @@ func ConfigureExecCommand(app *kingpin.Application, a *AwsVault) { BoolVar(&input.UseStdout) cmd.Arg("profile", "Name of the profile"). - Required(). + //Required(). HintAction(a.MustGetProfileNames). StringVar(&input.ProfileName) @@ -134,6 +134,17 @@ func ConfigureExecCommand(app *kingpin.Application, a *AwsVault) { return err } + if input.ProfileName == "" { + // If no profile provided select from configured AWS profiles + ProfileName, err := pickAwsProfile(f.ProfileNames()) + + if err != nil { + return fmt.Errorf("unable to select a 'profile'. Try --help: %w", err) + } + + input.ProfileName = ProfileName + } + exitcode := 0 if input.JSONDeprecated { exportCommandInput := ExportCommandInput{ diff --git a/cli/exec_test.go b/cli/exec_test.go index c2d259185..fc22c442a 100644 --- a/cli/exec_test.go +++ b/cli/exec_test.go @@ -3,7 +3,7 @@ package cli import ( "github.com/alecthomas/kingpin/v2" - "github.com/99designs/keyring" + "github.com/byteness/keyring" ) func ExampleExecCommand() { diff --git a/cli/export.go b/cli/export.go index 82dca9229..21465b230 100644 --- a/cli/export.go +++ b/cli/export.go @@ -8,11 +8,11 @@ import ( "os" "time" - "github.com/99designs/aws-vault/v7/iso8601" - "github.com/99designs/aws-vault/v7/vault" - "github.com/99designs/keyring" "github.com/alecthomas/kingpin/v2" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/byteness/aws-vault/v7/iso8601" + "github.com/byteness/aws-vault/v7/vault" + "github.com/byteness/keyring" ini "gopkg.in/ini.v1" ) @@ -60,7 +60,7 @@ func ConfigureExportCommand(app *kingpin.Application, a *AwsVault) { BoolVar(&input.UseStdout) cmd.Arg("profile", "Name of the profile"). - Required(). + //Required(). HintAction(a.MustGetProfileNames). StringVar(&input.ProfileName) @@ -79,6 +79,17 @@ func ConfigureExportCommand(app *kingpin.Application, a *AwsVault) { return err } + if input.ProfileName == "" { + // If no profile provided select from configured AWS profiles + ProfileName, err := pickAwsProfile(f.ProfileNames()) + + if err != nil { + return fmt.Errorf("unable to select a 'profile'. Try --help: %w", err) + } + + input.ProfileName = ProfileName + } + err = ExportCommand(input, f, keyring) app.FatalIfError(err, "exec") return nil diff --git a/cli/export_test.go b/cli/export_test.go index 9037923df..8f02e398a 100644 --- a/cli/export_test.go +++ b/cli/export_test.go @@ -3,7 +3,7 @@ package cli import ( "github.com/alecthomas/kingpin/v2" - "github.com/99designs/keyring" + "github.com/byteness/keyring" ) func ExampleExportCommand() { diff --git a/cli/global.go b/cli/global.go index 10561f82d..f5494e53e 100644 --- a/cli/global.go +++ b/cli/global.go @@ -7,10 +7,13 @@ import ( "os" "strings" - "github.com/99designs/aws-vault/v7/prompt" - "github.com/99designs/aws-vault/v7/vault" - "github.com/99designs/keyring" + "github.com/AlecAivazis/survey/v2" "github.com/alecthomas/kingpin/v2" + "github.com/byteness/aws-vault/v7/prompt" + "github.com/byteness/aws-vault/v7/vault" + "github.com/byteness/keyring" + "github.com/charmbracelet/huh" + "github.com/charmbracelet/lipgloss" isatty "github.com/mattn/go-isatty" "golang.org/x/term" ) @@ -187,3 +190,58 @@ func fileKeyringPassphrasePrompt(prompt string) (string, error) { fmt.Println() return string(b), nil } + +// Archived library github.com/AlecAivazis/survey/v2 +func pickAwsProfile(profiles []string) (string, error) { + var ProfileName string + + // the questions to ask + prompt := &survey.Select{ + Message: "Choose AWS profile:", + Options: profiles, + } + /*var countryQs = []*survey.Question{ + { + Name: "profileName", + Prompt: &survey.Select{ + Message: "Choose AWS profile:", + Options: f.ProfileNames(), + }, + Validate: survey.Required, + }, + } + + answers := struct { + ProfileName string + }{}*/ + + // ask the question + err := survey.AskOne(prompt, &ProfileName) + //err := survey.Ask(countryQs, &answers) + + return ProfileName, err +} + +// Maintained library github.com/charmbracelet/huh (TODO: needs more testing) +func pickAwsProfile2(profiles []string) (string, error) { + var ProfileName string + + // Convert to []huh.Option + var opts []huh.Option[string] + for _, p := range profiles { + opts = append(opts, huh.NewOption(p, p)) + } + form := huh.NewForm( + huh.NewGroup( + huh.NewSelect[string](). + Title("Choose AWS profile:"). + Options(opts...). + Value(&ProfileName))).WithHeight(9) + + err := form.Run() + blue := lipgloss.NewStyle().Foreground(lipgloss.Color("6")) + white := lipgloss.NewStyle().Foreground(lipgloss.Color("15")) + fmt.Printf("%s %s\n", white.Render("Selected profile:"), blue.Render(fmt.Sprintf("%s", ProfileName))) + + return ProfileName, err +} diff --git a/cli/list.go b/cli/list.go index 2a0aae253..63b0233e0 100644 --- a/cli/list.go +++ b/cli/list.go @@ -7,9 +7,9 @@ import ( "text/tabwriter" "time" - "github.com/99designs/aws-vault/v7/vault" - "github.com/99designs/keyring" + "github.com/byteness/keyring" "github.com/alecthomas/kingpin/v2" + "github.com/byteness/aws-vault/v7/vault" ) type ListCommandInput struct { diff --git a/cli/list_test.go b/cli/list_test.go index 161757ec5..b1055e749 100644 --- a/cli/list_test.go +++ b/cli/list_test.go @@ -3,7 +3,7 @@ package cli import ( "github.com/alecthomas/kingpin/v2" - "github.com/99designs/keyring" + "github.com/byteness/keyring" ) func ExampleListCommand() { diff --git a/cli/login.go b/cli/login.go index 7e248d7e9..2f3301294 100644 --- a/cli/login.go +++ b/cli/login.go @@ -11,13 +11,13 @@ import ( "strings" "time" - "github.com/99designs/aws-vault/v7/vault" - "github.com/99designs/keyring" "github.com/alecthomas/kingpin/v2" "github.com/aws/aws-sdk-go-v2/aws" awsconfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/sts" + "github.com/byteness/aws-vault/v7/vault" + "github.com/byteness/keyring" "github.com/skratchdot/open-golang/open" ) @@ -28,6 +28,7 @@ type LoginCommandInput struct { Config vault.ProfileConfig SessionDuration time.Duration NoSession bool + AutoLogout bool } func ConfigureLoginCommand(app *kingpin.Application, a *AwsVault) { @@ -43,6 +44,11 @@ func ConfigureLoginCommand(app *kingpin.Application, a *AwsVault) { Short('n'). BoolVar(&input.NoSession) + cmd.Flag("auto-logout", "Auto logout when starting a new login"). + Short('a'). + Envar("AWS_VAULT_AUTO_LOGOUT"). + BoolVar(&input.AutoLogout) + cmd.Flag("mfa-token", "The MFA token to use"). Short('t'). StringVar(&input.Config.MfaToken) @@ -81,7 +87,7 @@ func ConfigureLoginCommand(app *kingpin.Application, a *AwsVault) { }) } -func getCredsProvider(input LoginCommandInput, config *vault.ProfileConfig, keyring keyring.Keyring) (credsProvider aws.CredentialsProvider, err error) { +func getCredsProvider(input LoginCommandInput, config *vault.ProfileConfig, f *vault.ConfigFile, keyring keyring.Keyring) (credsProvider aws.CredentialsProvider, err error) { if input.ProfileName == "" { // When no profile is specified, source credentials from the environment configFromEnv, err := awsconfig.NewEnvConfig() @@ -90,7 +96,32 @@ func getCredsProvider(input LoginCommandInput, config *vault.ProfileConfig, keyr } if configFromEnv.Credentials.AccessKeyID == "" { - return nil, fmt.Errorf("argument 'profile' not provided, nor any AWS env vars found. Try --help") + // If no credentials from the environment ask for profile + ProfileName, err := pickAwsProfile(f.ProfileNames()) + + if err != nil { + return nil, fmt.Errorf("unable to select a 'profile', nor any AWS env vars found. Try --help: %w", err) + } + + // Load config from selected AWS profile + config, err := vault.NewConfigLoader(input.Config, f, ProfileName).GetProfileConfig(ProfileName) + if err != nil { + return nil, fmt.Errorf("Error loading config: %w", err) + } + + // Use selected profile from the AWS config file + ckr := &vault.CredentialKeyring{Keyring: keyring} + t := vault.TempCredentialsCreator{ + Keyring: ckr, + DisableSessions: input.NoSession, + DisableSessionsForProfile: config.ProfileName, + } + credsProvider, err = t.GetProviderForProfile(config) + if err != nil { + return nil, fmt.Errorf("profile %s: %w", ProfileName, err) + } + + return credsProvider, err } credsProvider = credentials.StaticCredentialsProvider{Value: configFromEnv.Credentials} @@ -119,7 +150,7 @@ func LoginCommand(ctx context.Context, input LoginCommandInput, f *vault.ConfigF return fmt.Errorf("Error loading config: %w", err) } - credsProvider, err := getCredsProvider(input, config, keyring) + credsProvider, err := getCredsProvider(input, config, f, keyring) if err != nil { return err } @@ -168,8 +199,19 @@ func LoginCommand(ctx context.Context, input LoginCommandInput, f *vault.ConfigF return err } - loginURL := fmt.Sprintf("%s?Action=login&Issuer=aws-vault&Destination=%s&SigninToken=%s", - loginURLPrefix, url.QueryEscape(destination), url.QueryEscape(signinToken)) + var loginURL string + + if input.AutoLogout { + // Use logout URL and redirect to login + redirectURL := fmt.Sprintf("%s?Action=login&Issuer=aws-vault&Destination=%s&SigninToken=%s", + loginURLPrefix, destination, signinToken) + loginURL = fmt.Sprintf("https://us-east-1.signin.aws.amazon.com/oauth?Action=logout&redirect_uri=%s", + url.QueryEscape(redirectURL)) + } else { + // Go directly to login + loginURL = fmt.Sprintf("%s?Action=login&Issuer=aws-vault&Destination=%s&SigninToken=%s", + loginURLPrefix, url.QueryEscape(destination), url.QueryEscape(signinToken)) + } if input.UseStdout { fmt.Println(loginURL) @@ -181,7 +223,7 @@ func LoginCommand(ctx context.Context, input LoginCommandInput, f *vault.ConfigF } func generateLoginURL(region string, path string) (string, string) { - loginURLPrefix := "https://signin.aws.amazon.com/federation" + loginURLPrefix := "https://us-east-1.signin.aws.amazon.com/federation" destination := "https://console.aws.amazon.com/" if region != "" { diff --git a/cli/proxy.go b/cli/proxy.go index 1ab260614..54c4e615b 100644 --- a/cli/proxy.go +++ b/cli/proxy.go @@ -5,8 +5,8 @@ import ( "os/signal" "syscall" - "github.com/99designs/aws-vault/v7/server" "github.com/alecthomas/kingpin/v2" + "github.com/byteness/aws-vault/v7/server" ) func ConfigureProxyCommand(app *kingpin.Application) { diff --git a/cli/remove.go b/cli/remove.go index d9d7f47f0..9732a536c 100644 --- a/cli/remove.go +++ b/cli/remove.go @@ -4,10 +4,10 @@ import ( "fmt" "strings" - "github.com/99designs/aws-vault/v7/prompt" - "github.com/99designs/aws-vault/v7/vault" - "github.com/99designs/keyring" + "github.com/byteness/keyring" "github.com/alecthomas/kingpin/v2" + "github.com/byteness/aws-vault/v7/prompt" + "github.com/byteness/aws-vault/v7/vault" ) type RemoveCommandInput struct { diff --git a/cli/rotate.go b/cli/rotate.go index 372e1f1f9..3cb808578 100644 --- a/cli/rotate.go +++ b/cli/rotate.go @@ -6,11 +6,11 @@ import ( "log" "time" - "github.com/99designs/aws-vault/v7/vault" - "github.com/99designs/keyring" "github.com/alecthomas/kingpin/v2" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/byteness/aws-vault/v7/vault" + "github.com/byteness/keyring" ) type RotateCommandInput struct { @@ -29,21 +29,33 @@ func ConfigureRotateCommand(app *kingpin.Application, a *AwsVault) { BoolVar(&input.NoSession) cmd.Arg("profile", "Name of the profile"). - Required(). + //Required(). HintAction(a.MustGetProfileNames). StringVar(&input.ProfileName) cmd.Action(func(c *kingpin.ParseContext) (err error) { input.Config.MfaPromptMethod = a.PromptDriver(false) - keyring, err := a.Keyring() + + f, err := a.AwsConfigFile() if err != nil { return err } - f, err := a.AwsConfigFile() + keyring, err := a.Keyring() if err != nil { return err } + if input.ProfileName == "" { + // If no profile provided select from configured AWS profiles + ProfileName, err := pickAwsProfile(f.ProfileNames()) + + if err != nil { + return fmt.Errorf("unable to select a 'profile'. Try --help: %w", err) + } + + input.ProfileName = ProfileName + } + err = RotateCommand(input, f, keyring) app.FatalIfError(err, "rotate") return nil diff --git a/contrib/completions/zsh/aws-vault.zsh b/contrib/completions/zsh/aws-vault.zsh index 3cbbdba75..da935461b 100644 --- a/contrib/completions/zsh/aws-vault.zsh +++ b/contrib/completions/zsh/aws-vault.zsh @@ -1,24 +1,30 @@ #compdef aws-vault _aws-vault() { - local i - for (( i=2; i < CURRENT; i++ )); do - if [[ ${words[i]} == -- ]]; then - shift $i words - (( CURRENT -= i )) - _normal - return - fi - done + _arguments -C \ + '1: :->command' \ + '2: :->profiles' - local matches=($(${words[1]} --completion-bash ${(@)words[2,$CURRENT]})) - compadd -a matches + case $state in + command) + local -a commands=( $(${words[1]} --completion-bash) ) + _describe -t commands 'Commands' commands - if [[ $compstate[nmatches] -eq 0 && $words[$CURRENT] != -* ]]; then - _files - fi + ;; + profiles) + case "${words[2]}" in + exec|login|remove|rm|rotate) + local -a profiles=( $(cat ~/.aws/config | awk '/^\[profile/ {print $2;}' | tr -d \]) ) + _describe -t profiles 'AWS Profiles' profiles + ;; + esac + ;; + args) + _describe -t args 'Args' args + esac } + if [[ "$(basename -- ${(%):-%x})" != "_aws-vault" ]]; then compdef _aws-vault aws-vault fi diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 69f0c76b0..5022fac51 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -1,6 +1,6 @@ FROM debian:bullseye-slim RUN apt update && apt install -y curl -RUN curl -fLs -o /usr/local/bin/aws-vault https://github.com/99designs/aws-vault/releases/download/v6.3.1/aws-vault-linux-amd64 && chmod 755 /usr/local/bin/aws-vault +RUN curl -fLs -o /usr/local/bin/aws-vault https://github.com/byteness/aws-vault/releases/latest/download/aws-vault-linux-amd64 && chmod 755 /usr/local/bin/aws-vault ENV AWS_VAULT_BACKEND=file ENTRYPOINT ["/usr/local/bin/aws-vault"] diff --git a/go.mod b/go.mod index 70522e8f0..50d06528d 100644 --- a/go.mod +++ b/go.mod @@ -1,39 +1,69 @@ -module github.com/99designs/aws-vault/v7 +module github.com/byteness/aws-vault/v7 -go 1.20 +go 1.24 require ( - github.com/99designs/keyring v1.2.2 - github.com/alecthomas/kingpin/v2 v2.3.2 - github.com/aws/aws-sdk-go-v2 v1.17.7 - github.com/aws/aws-sdk-go-v2/config v1.18.19 - github.com/aws/aws-sdk-go-v2/credentials v1.13.18 - github.com/aws/aws-sdk-go-v2/service/iam v1.19.8 - github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 - github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 - github.com/google/go-cmp v0.5.9 - github.com/mattn/go-isatty v0.0.18 - github.com/mattn/go-tty v0.0.4 + github.com/AlecAivazis/survey/v2 v2.3.7 + github.com/alecthomas/kingpin/v2 v2.4.0 + github.com/aws/aws-sdk-go-v2 v1.38.0 + github.com/aws/aws-sdk-go-v2/config v1.31.0 + github.com/aws/aws-sdk-go-v2/credentials v1.18.4 + github.com/aws/aws-sdk-go-v2/service/iam v1.46.0 + github.com/aws/aws-sdk-go-v2/service/sso v1.28.0 + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.0 + github.com/aws/aws-sdk-go-v2/service/sts v1.37.0 + github.com/byteness/keyring v1.3.3 + github.com/charmbracelet/huh v0.7.0 + github.com/charmbracelet/lipgloss v1.1.0 + github.com/google/go-cmp v0.7.0 + github.com/mattn/go-isatty v0.0.20 + github.com/mattn/go-tty v0.0.7 github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 - golang.org/x/term v0.6.0 + golang.org/x/term v0.34.0 gopkg.in/ini.v1 v1.67.0 ) require ( - github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 // indirect - github.com/aws/smithy-go v1.13.5 // indirect - github.com/danieljoos/wincred v1.1.2 // indirect - github.com/dvsekhvalnov/jose2go v1.5.0 // indirect - github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect - github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect - github.com/mtibben/percent v0.2.1 // indirect + github.com/atotto/clipboard v0.1.4 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 // indirect + github.com/aws/smithy-go v1.22.5 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/byteness/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/byteness/go-libsecret v0.0.0-20250705200722-75549abfe79c // indirect + github.com/byteness/percent v0.2.2 // indirect + github.com/catppuccin/go v0.3.0 // indirect + github.com/charmbracelet/bubbles v0.21.0 // indirect + github.com/charmbracelet/bubbletea v1.3.4 // indirect + github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect + github.com/charmbracelet/x/ansi v0.8.0 // indirect + github.com/charmbracelet/x/cellbuf v0.0.13 // indirect + github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect + github.com/charmbracelet/x/term v0.2.1 // indirect + github.com/danieljoos/wincred v1.2.2 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dvsekhvalnov/jose2go v1.8.0 // indirect + github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-localereader v0.0.1 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect + github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect + github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/muesli/termenv v0.16.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect - golang.org/x/sys v0.6.0 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.23.0 // indirect ) diff --git a/go.sum b/go.sum index 605baf9a8..9e49bca66 100644 --- a/go.sum +++ b/go.sum @@ -1,92 +1,199 @@ -github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= -github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= -github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= -github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= -github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU= -github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= +github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= +github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/aws/aws-sdk-go-v2 v1.17.7 h1:CLSjnhJSTSogvqUGhIC6LqFKATMRexcxLZ0i/Nzk9Eg= -github.com/aws/aws-sdk-go-v2 v1.17.7/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= -github.com/aws/aws-sdk-go-v2/config v1.18.19 h1:AqFK6zFNtq4i1EYu+eC7lcKHYnZagMn6SW171la0bGw= -github.com/aws/aws-sdk-go-v2/config v1.18.19/go.mod h1:XvTmGMY8d52ougvakOv1RpiTLPz9dlG/OQHsKU/cMmY= -github.com/aws/aws-sdk-go-v2/credentials v1.13.18 h1:EQMdtHwz0ILTW1hoP+EwuWhwCG1hD6l3+RWFQABET4c= -github.com/aws/aws-sdk-go-v2/credentials v1.13.18/go.mod h1:vnwlwjIe+3XJPBYKu1et30ZPABG3VaXJYr8ryohpIyM= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 h1:gt57MN3liKiyGopcqgNzJb2+d9MJaKT/q1OksHNXVE4= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1/go.mod h1:lfUx8puBRdM5lVVMQlwt2v+ofiG/X6Ms+dy0UkG/kXw= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 h1:sJLYcS+eZn5EeNINGHSCRAwUJMFVqklwkH36Vbyai7M= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31/go.mod h1:QT0BqUvX1Bh2ABdTGnjqEjvjzrCfIniM9Sc8zn9Yndo= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 h1:1mnRASEKnkqsntcxHaysxwgVoUUp5dkiB+l3llKnqyg= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25/go.mod h1:zBHOPwhBc3FlQjQJE/D3IfPWiWaQmT06Vq9aNukDo0k= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 h1:p5luUImdIqywn6JpQsW3tq5GNOxKmOnEpybzPx+d1lk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32/go.mod h1:XGhIBZDEgfqmFIugclZ6FU7v75nHhBDtzuB4xB/tEi4= -github.com/aws/aws-sdk-go-v2/service/iam v1.19.8 h1:kQsBeGgm68kT0xc90spgC5qEOQGH74V2bFqgBgG21Bo= -github.com/aws/aws-sdk-go-v2/service/iam v1.19.8/go.mod h1:lf/oAjt//UvPsmnOgPT61F+q4K6U0q4zDd1s1yx2NZs= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 h1:5LHn8JQ0qvjD9L9JhMtylnkcw7j05GDZqM9Oin6hpr0= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25/go.mod h1:/95IA+0lMnzW6XzqYJRpjjsAbKEORVeO0anQqjd2CNU= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 h1:5V7DWLBd7wTELVz5bPpwzYy/sikk0gsgZfj40X+l5OI= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.6/go.mod h1:Y1VOmit/Fn6Tz1uFAeCO6Q7M2fmfXSCLeL5INVYsLuY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 h1:B8cauxOH1W1v7rd8RdI/MWnoR4Ze0wIHWrb90qczxj4= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6/go.mod h1:Lh/bc9XUf8CfOY6Jp5aIkQtN+j1mc+nExc+KXj9jx2s= -github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 h1:bWNgNdRko2x6gqa0blfATqAZKZokPIeM1vfmQt2pnvM= -github.com/aws/aws-sdk-go-v2/service/sts v1.18.7/go.mod h1:JuTnSoeePXmMVe9G8NcjjwgOKEfZ4cOjMuT2IBT/2eI= -github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= -github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= -github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= +github.com/aws/aws-sdk-go-v2 v1.38.0 h1:UCRQ5mlqcFk9HJDIqENSLR3wiG1VTWlyUfLDEvY7RxU= +github.com/aws/aws-sdk-go-v2 v1.38.0/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= +github.com/aws/aws-sdk-go-v2/config v1.31.0 h1:9yH0xiY5fUnVNLRWO0AtayqwU1ndriZdN78LlhruJR4= +github.com/aws/aws-sdk-go-v2/config v1.31.0/go.mod h1:VeV3K72nXnhbe4EuxxhzsDc/ByrCSlZwUnWH52Nde/I= +github.com/aws/aws-sdk-go-v2/credentials v1.18.4 h1:IPd0Algf1b+Qy9BcDp0sCUcIWdCQPSzDoMK3a8pcbUM= +github.com/aws/aws-sdk-go-v2/credentials v1.18.4/go.mod h1:nwg78FjH2qvsRM1EVZlX9WuGUJOL5od+0qvm0adEzHk= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.3 h1:GicIdnekoJsjq9wqnvyi2elW6CGMSYKhdozE7/Svh78= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.3/go.mod h1:R7BIi6WNC5mc1kfRM7XM/VHC3uRWkjc396sfabq4iOo= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 h1:o9RnO+YZ4X+kt5Z7Nvcishlz0nksIt2PIzDglLMP0vA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3/go.mod h1:+6aLJzOG1fvMOyzIySYjOFjcguGvVRL68R+uoRencN4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 h1:joyyUFhiTQQmVK6ImzNU9TQSNRNeD9kOklqTzyk5v6s= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3/go.mod h1:+vNIyZQP3b3B1tSLI0lxvrU9cfM7gpdRXMFfm67ZcPc= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/service/iam v1.46.0 h1:bJgrqPT2vy+OrJpSeVfZ4e4zaD/EVdcq+5yxDtUOql0= +github.com/aws/aws-sdk-go-v2/service/iam v1.46.0/go.mod h1:WsQuuejKHNC3UWs+n4usF+nNy1DFGYgWRugqFf+gGD4= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 h1:ieRzyHXypu5ByllM7Sp4hC5f/1Fy5wqxqY0yB85hC7s= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3/go.mod h1:O5ROz8jHiOAKAwx179v+7sHMhfobFVi6nZt8DEyiYoM= +github.com/aws/aws-sdk-go-v2/service/sso v1.28.0 h1:Mc/MKBf2m4VynyJkABoVEN+QzkfLqGj0aiJuEe7cMeM= +github.com/aws/aws-sdk-go-v2/service/sso v1.28.0/go.mod h1:iS5OmxEcN4QIPXARGhavH7S8kETNL11kym6jhoS7IUQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.0 h1:6csaS/aJmqZQbKhi1EyEMM7yBW653Wy/B9hnBofW+sw= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.0/go.mod h1:59qHWaY5B+Rs7HGTuVGaC32m0rdpQ68N8QCN3khYiqs= +github.com/aws/aws-sdk-go-v2/service/sts v1.37.0 h1:MG9VFW43M4A8BYeAfaJJZWrroinxeTi2r3+SnmLQfSA= +github.com/aws/aws-sdk-go-v2/service/sts v1.37.0/go.mod h1:JdeBDPgpJfuS6rU/hNglmOigKhyEZtBmbraLE4GK1J8= +github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= +github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= +github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= +github.com/byteness/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:HFl8GFmwK19hYuXB8OQ0rTO9WOCgZY9JUy964zaYawY= +github.com/byteness/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:9HlL8SWBRtCZE7sCNq+c3//H/oHywgSwtocmPTdOij8= +github.com/byteness/go-libsecret v0.0.0-20250705200722-75549abfe79c h1:acX3x2Ka/6jQt3inHLNUuL1IKxb/j4dNMbuL6B/N324= +github.com/byteness/go-libsecret v0.0.0-20250705200722-75549abfe79c/go.mod h1:eVg/Qgq8PRiBljsgvBLlVpMSrLecEY8pINiVRKQYYdc= +github.com/byteness/keyring v1.3.3 h1:CkZEZsiV2+V0yKrHxSf+IG2d5RYRy9S1vD3qFQqtn4Q= +github.com/byteness/keyring v1.3.3/go.mod h1:Cp00SJzoU72YKXnambKCbVPcTjqW8gbBzg0Ks3qRFYg= +github.com/byteness/percent v0.2.2 h1:vnIFh8WBR1xoC+U2etz0EMB1cgp+vsK6vynqTCeDziU= +github.com/byteness/percent v0.2.2/go.mod h1:nwavge92FhIyfnldz4YWZD8uxPVvdh8NlzLRd1VYRDs= +github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY= +github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= +github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= +github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= +github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI= +github.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= +github.com/charmbracelet/huh v0.7.0 h1:W8S1uyGETgj9Tuda3/JdVkc3x7DBLZYPZc4c+/rnRdc= +github.com/charmbracelet/huh v0.7.0/go.mod h1:UGC3DZHlgOKHvHC07a5vHag41zzhpPFj34U92sOmyuk= +github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= +github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= +github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= +github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/conpty v0.1.0 h1:4zc8KaIcbiL4mghEON8D72agYtSeIgq8FSThSPQIb+U= +github.com/charmbracelet/x/conpty v0.1.0/go.mod h1:rMFsDJoDwVmiYM10aD4bH2XiRgwI7NYJtQgl5yskjEQ= +github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86 h1:JSt3B+U9iqk37QUU2Rvb6DSBYRLtWqFqfxf8l5hOZUA= +github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0= +github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= +github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 h1:qko3AQ4gK1MTS/de7F5hPGx6/k1u0w4TeYmBFwzYVP4= +github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ= +github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY= +github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo= +github.com/charmbracelet/x/xpty v0.1.2 h1:Pqmu4TEJ8KeA9uSkISKMU3f+C1F6OGBn8ABuGlqCbtI= +github.com/charmbracelet/x/xpty v0.1.2/go.mod h1:XK2Z0id5rtLWcpeNiMYBccNNBrP2IJnzHI0Lq13Xzq4= +github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= +github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= -github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= -github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= -github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= -github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/dvsekhvalnov/jose2go v1.8.0 h1:LqkkVKAlHFfH9LOEl5fe4p/zL02OhWE7pCufMBG2jLA= +github.com/dvsekhvalnov/jose2go v1.8.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= +github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E= -github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28= -github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= -github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-tty v0.0.7 h1:KJ486B6qI8+wBO7kQxYgmmEFDaFEE96JMBQ7h400N8Q= +github.com/mattn/go-tty v0.0.7/go.mod h1:f2i5ZOvXBU/tCABmLmOfzLz9azMo5wdAaElRNnJKr+k= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= +github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index fc6b1f708..a864a11dd 100644 --- a/main.go +++ b/main.go @@ -3,8 +3,8 @@ package main import ( "os" - "github.com/99designs/aws-vault/v7/cli" "github.com/alecthomas/kingpin/v2" + "github.com/byteness/aws-vault/v7/cli" ) // Version is provided at compile time diff --git a/server/ec2alias_windows.go b/server/ec2alias_windows.go index adf948f75..52b9548f2 100644 --- a/server/ec2alias_windows.go +++ b/server/ec2alias_windows.go @@ -13,6 +13,7 @@ var alreadyRegisteredLocalised = []string{ "The object already exists", "Das Objekt ist bereits vorhanden", "El objeto ya existe", + "Objektet findes allerede", } var runAsAdministratorLocalised = []string{ @@ -20,6 +21,8 @@ var runAsAdministratorLocalised = []string{ // truncate before 'Umlaut' to avoid encoding problems coming from Windows cmd "Als Administrator ausf", "Ejecutar como administrador", + // truncate before 'ΓΈ' to avoid encoding problems coming from Windows cmd + "r som administrator", } func msgFound(localised []string, toTest string) bool { diff --git a/server/ec2server.go b/server/ec2server.go index 63ccd2969..c9d744e99 100644 --- a/server/ec2server.go +++ b/server/ec2server.go @@ -9,8 +9,8 @@ import ( "net/http" "time" - "github.com/99designs/aws-vault/v7/iso8601" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/byteness/aws-vault/v7/iso8601" ) const ec2CredentialsServerAddr = "127.0.0.1:9099" @@ -48,7 +48,7 @@ func startEc2CredentialsServer(credsProvider aws.CredentialsProvider, region str // used by AWS SDK to determine region router.HandleFunc("/latest/dynamic/instance-identity/document", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, `{"region": "`+region+`"}`) + fmt.Fprintf(w, `{"region": "%s"}`, region) }) router.HandleFunc("/latest/meta-data/iam/security-credentials/local-credentials", credsHandler(credsProvider)) @@ -74,7 +74,7 @@ func withSecurityChecks(next *http.ServeMux) http.HandlerFunc { // Check that the request is to 169.254.169.254 // Without this it's possible for an attacker to mount a DNS rebinding attack - // See https://github.com/99designs/aws-vault/issues/578 + // See https://github.com/byteness/aws-vault/issues/578 if r.Host != ec2MetadataEndpointIP && r.Host != ec2MetadataEndpointAddr { http.Error(w, fmt.Sprintf("Access denied for host '%s'", r.Host), http.StatusUnauthorized) return diff --git a/server/ecsserver.go b/server/ecsserver.go index 488d3f767..53dd531aa 100644 --- a/server/ecsserver.go +++ b/server/ecsserver.go @@ -12,10 +12,10 @@ import ( "strings" "sync" - "github.com/99designs/aws-vault/v7/iso8601" - "github.com/99designs/aws-vault/v7/vault" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/sts" + "github.com/byteness/aws-vault/v7/iso8601" + "github.com/byteness/aws-vault/v7/vault" ) func writeErrorMessage(w http.ResponseWriter, msg string, statusCode int) { diff --git a/vault/config_test.go b/vault/config_test.go index b9f10375b..95671ca3f 100644 --- a/vault/config_test.go +++ b/vault/config_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - "github.com/99designs/aws-vault/v7/vault" + "github.com/byteness/aws-vault/v7/vault" "github.com/google/go-cmp/cmp" ) diff --git a/vault/credentialkeyring.go b/vault/credentialkeyring.go index d57ee6fcc..a5ffcdf4a 100644 --- a/vault/credentialkeyring.go +++ b/vault/credentialkeyring.go @@ -4,7 +4,7 @@ import ( "encoding/json" "fmt" - "github.com/99designs/keyring" + "github.com/byteness/keyring" "github.com/aws/aws-sdk-go-v2/aws" ) diff --git a/vault/mfa.go b/vault/mfa.go index eb5de34ba..925917875 100644 --- a/vault/mfa.go +++ b/vault/mfa.go @@ -2,14 +2,10 @@ package vault import ( "errors" - "fmt" "log" - "os" - "os/exec" - "strings" - "github.com/99designs/aws-vault/v7/prompt" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/byteness/aws-vault/v7/prompt" ) // Mfa contains options for an MFA device @@ -47,13 +43,5 @@ func NewMfa(config *ProfileConfig) Mfa { } func ProcessMfaProvider(processCmd string) (string, error) { - cmd := exec.Command("/bin/sh", "-c", processCmd) - cmd.Stderr = os.Stderr - - out, err := cmd.Output() - if err != nil { - return "", fmt.Errorf("process provider: %w", err) - } - - return strings.TrimSpace(string(out)), nil + return executeMFACommand(processCmd) } diff --git a/vault/mfa_unix.go b/vault/mfa_unix.go new file mode 100644 index 000000000..d470ca0fc --- /dev/null +++ b/vault/mfa_unix.go @@ -0,0 +1,23 @@ +//go:build linux || darwin || freebsd || openbsd +// +build linux darwin freebsd openbsd + +package vault + +import ( + "fmt" + "os" + "os/exec" + "strings" +) + +func executeMFACommand(processCmd string) (string, error) { + cmd := exec.Command("/bin/sh", "-c", processCmd) + cmd.Stderr = os.Stderr + + out, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("process provider: %w", err) + } + + return strings.TrimSpace(string(out)), nil +} diff --git a/vault/mfa_windows.go b/vault/mfa_windows.go new file mode 100644 index 000000000..038a5cbf4 --- /dev/null +++ b/vault/mfa_windows.go @@ -0,0 +1,28 @@ +//go:build windows +// +build windows + +package vault + +import ( + "fmt" + "os" + "os/exec" + "strings" + "syscall" +) + +func executeMFACommand(processCmd string) (string, error) { + // On windows, its quite involved to launch a process if the binary involved is in a path with spaces + // See https://github.com/golang/go/issues/17149 for details and workaround proposals + shell := os.Getenv("SystemRoot") + "\\System32\\cmd.exe" + cmd := exec.Command(shell) + cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: "/C \"" + processCmd + "\""} + cmd.Stderr = os.Stderr + + out, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("process provider: %w", err) + } + + return strings.TrimSpace(string(out)), nil +} diff --git a/vault/oidctokenkeyring.go b/vault/oidctokenkeyring.go index 4bd13c878..70d1f01f1 100644 --- a/vault/oidctokenkeyring.go +++ b/vault/oidctokenkeyring.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "github.com/99designs/keyring" + "github.com/byteness/keyring" "github.com/aws/aws-sdk-go-v2/service/ssooidc" ) diff --git a/vault/sessionkeyring.go b/vault/sessionkeyring.go index dbd984cfb..0291ba666 100644 --- a/vault/sessionkeyring.go +++ b/vault/sessionkeyring.go @@ -10,7 +10,7 @@ import ( "strings" "time" - "github.com/99designs/keyring" + "github.com/byteness/keyring" ststypes "github.com/aws/aws-sdk-go-v2/service/sts/types" ) diff --git a/vault/sessionkeyring_test.go b/vault/sessionkeyring_test.go index e3583d3e4..170cf6195 100644 --- a/vault/sessionkeyring_test.go +++ b/vault/sessionkeyring_test.go @@ -3,7 +3,7 @@ package vault_test import ( "testing" - "github.com/99designs/aws-vault/v7/vault" + "github.com/byteness/aws-vault/v7/vault" ) func TestIsSessionKey(t *testing.T) { diff --git a/vault/ssorolecredentialsprovider.go b/vault/ssorolecredentialsprovider.go index 25c008b61..9854f4ee3 100644 --- a/vault/ssorolecredentialsprovider.go +++ b/vault/ssorolecredentialsprovider.go @@ -9,7 +9,7 @@ import ( "os" "time" - "github.com/99designs/keyring" + "github.com/byteness/keyring" "github.com/aws/aws-sdk-go-v2/aws" awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http" "github.com/aws/aws-sdk-go-v2/service/sso" diff --git a/vault/vault.go b/vault/vault.go index 450fea591..5a6833ed6 100644 --- a/vault/vault.go +++ b/vault/vault.go @@ -7,11 +7,11 @@ import ( "os" "time" - "github.com/99designs/keyring" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/sso" "github.com/aws/aws-sdk-go-v2/service/ssooidc" "github.com/aws/aws-sdk-go-v2/service/sts" + "github.com/byteness/keyring" ) var defaultExpirationWindow = 5 * time.Minute diff --git a/vault/vault_test.go b/vault/vault_test.go index 75a047ad8..75812bab3 100644 --- a/vault/vault_test.go +++ b/vault/vault_test.go @@ -4,8 +4,8 @@ import ( "os" "testing" - "github.com/99designs/aws-vault/v7/vault" - "github.com/99designs/keyring" + "github.com/byteness/keyring" + "github.com/byteness/aws-vault/v7/vault" ) func TestUsageWebIdentityExample(t *testing.T) { From 1912e2689df22de712d9843de65579414cbddebc Mon Sep 17 00:00:00 2001 From: Lucas Almeida Date: Sun, 28 Sep 2025 17:10:03 -0300 Subject: [PATCH 5/5] fix: source chaining treated like role chaining --- vault/vault.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vault/vault.go b/vault/vault.go index 5a6833ed6..8503e5082 100644 --- a/vault/vault.go +++ b/vault/vault.go @@ -254,9 +254,9 @@ func (t *TempCredentialsCreator) getSourceCredWithSession(config *ProfileConfig, return nil, err } - isChainedCredentialSource := config.ChainedFromProfile != nil + isRoleChaining := config.ChainedFromProfile != nil && config.ChainedFromProfile.RoleARN != "" - if config.HasRole() && !isChainedCredentialSource { + if config.HasRole() && !isRoleChaining { isMfaChained := config.MfaSerial != "" && config.MfaSerial == t.chainedMfa if isMfaChained { config.MfaSerial = "" @@ -265,7 +265,7 @@ func (t *TempCredentialsCreator) getSourceCredWithSession(config *ProfileConfig, return NewAssumeRoleProvider(sourcecredsProvider, t.Keyring.Keyring, config, !t.DisableCache) } - if isMasterCredentialsProvider(sourcecredsProvider) || isChainedCredentialSource { + if isMasterCredentialsProvider(sourcecredsProvider) || isRoleChaining { canUseGetSessionToken, reason := t.canUseGetSessionToken(config) if !canUseGetSessionToken { log.Printf("profile %s: skipping GetSessionToken because %s", config.ProfileName, reason)