refactor: replace aws CLI with argocd-k8s-auth (#8032)

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
This commit is contained in:
Alexander Matyushentsev 2022-04-14 17:25:08 -07:00 committed by GitHub
parent a7214a0985
commit 655be25f87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 120 additions and 35 deletions

View file

@ -29,8 +29,7 @@ COPY hack/install.sh hack/tool-versions.sh ./
COPY hack/installers installers
RUN ./install.sh helm-linux && \
INSTALL_PATH=/usr/local/bin ./install.sh kustomize && \
./install.sh awscli-linux
INSTALL_PATH=/usr/local/bin ./install.sh kustomize
####################################################################################################
# Argo CD Base - used as the base for both the release and dev argocd images
@ -57,11 +56,9 @@ COPY hack/gpg-wrapper.sh /usr/local/bin/gpg-wrapper.sh
COPY hack/git-verify-wrapper.sh /usr/local/bin/git-verify-wrapper.sh
COPY --from=builder /usr/local/bin/helm /usr/local/bin/helm
COPY --from=builder /usr/local/bin/kustomize /usr/local/bin/kustomize
COPY --from=builder /usr/local/aws-cli/v2/current/dist /usr/local/aws-cli/v2/current/dist
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
# keep uid_entrypoint.sh for backward compatibility
RUN ln -s /usr/local/bin/entrypoint.sh /usr/local/bin/uid_entrypoint.sh && \
ln -s /usr/local/aws-cli/v2/current/dist/aws /usr/local/bin/aws
RUN ln -s /usr/local/bin/entrypoint.sh /usr/local/bin/uid_entrypoint.sh
# support for mounting configuration from a configmap
WORKDIR /app/config/ssh
@ -127,6 +124,7 @@ RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-application-controller && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-dex && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-notifications && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-applicationset-controller
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-applicationset-controller && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-k8s-auth
USER 999
USER 999

View file

@ -0,0 +1,24 @@
package commands
import (
"github.com/spf13/cobra"
)
const (
cliName = "argocd-k8s-auth"
)
func NewCommand() *cobra.Command {
var command = &cobra.Command{
Use: cliName,
Short: "argocd-k8s-auth a set of commands to generate k8s auth token",
DisableAutoGenTag: true,
Run: func(c *cobra.Command, args []string) {
c.HelpFunc()(c, args)
},
}
command.AddCommand(newAWSCommand())
return command
}

View file

@ -0,0 +1,79 @@
package commands
import (
"encoding/base64"
"encoding/json"
"fmt"
"os"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientauthv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
"github.com/argoproj/argo-cd/v2/util/errors"
)
const (
clusterIDHeader = "x-k8s-aws-id"
// The sts GetCallerIdentity request is valid for 15 minutes regardless of this parameters value after it has been
// signed, but we set this unused parameter to 60 for legacy reasons (we check for a value between 0 and 60 on the
// server side in 0.3.0 or earlier). IT IS IGNORED. If we can get STS to support x-amz-expires, then we should
// set this parameter to the actual expiration, and make it configurable.
requestPresignParam = 60
// The actual token expiration (presigned STS urls are valid for 15 minutes after timestamp in x-amz-date).
presignedURLExpiration = 15 * time.Minute
v1Prefix = "k8s-aws-v1."
)
// newAWSCommand returns a new instance of an aws command that generates k8s auth token
// implementation is "inspired" by https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/e61f537662b64092ed83cb76e600e023f627f628/pkg/token/token.go#L316
func newAWSCommand() *cobra.Command {
var (
clusterName string
roleARN string
)
var command = &cobra.Command{
Use: "aws",
Run: func(c *cobra.Command, args []string) {
sess, err := session.NewSession()
errors.CheckError(err)
stsAPI := sts.New(sess)
if roleARN != "" {
creds := stscreds.NewCredentials(sess, roleARN)
stsAPI = sts.New(sess, &aws.Config{Credentials: creds})
}
request, _ := stsAPI.GetCallerIdentityRequest(&sts.GetCallerIdentityInput{})
request.HTTPRequest.Header.Add(clusterIDHeader, clusterName)
presignedURLString, err := request.Presign(requestPresignParam)
errors.CheckError(err)
token := v1Prefix + base64.RawURLEncoding.EncodeToString([]byte(presignedURLString))
// Set token expiration to 1 minute before the presigned URL expires for some cushion
tokenExpiration := time.Now().Local().Add(presignedURLExpiration - 1*time.Minute)
_, _ = fmt.Fprint(os.Stdout, formatJSON(token, tokenExpiration))
},
}
command.Flags().StringVar(&clusterName, "cluster-name", "", "AWS Cluster name")
command.Flags().StringVar(&roleARN, "role-arn", "", "AWS Role ARN")
return command
}
func formatJSON(token string, expiration time.Time) string {
expirationTimestamp := metav1.NewTime(expiration)
execInput := &clientauthv1beta1.ExecCredential{
TypeMeta: metav1.TypeMeta{
APIVersion: "client.authentication.k8s.io/v1beta1",
Kind: "ExecCredential",
},
Status: &clientauthv1beta1.ExecCredentialStatus{
ExpirationTimestamp: &expirationTimestamp,
Token: token,
},
}
enc, _ := json.Marshal(execInput)
return string(enc)
}

View file

@ -11,6 +11,7 @@ import (
cmpserver "github.com/argoproj/argo-cd/v2/cmd/argocd-cmp-server/commands"
dex "github.com/argoproj/argo-cd/v2/cmd/argocd-dex/commands"
gitaskpass "github.com/argoproj/argo-cd/v2/cmd/argocd-git-ask-pass/commands"
k8sauth "github.com/argoproj/argo-cd/v2/cmd/argocd-k8s-auth/commands"
notification "github.com/argoproj/argo-cd/v2/cmd/argocd-notification/commands"
reposerver "github.com/argoproj/argo-cd/v2/cmd/argocd-repo-server/commands"
apiserver "github.com/argoproj/argo-cd/v2/cmd/argocd-server/commands"
@ -47,6 +48,8 @@ func main() {
command = gitaskpass.NewCommand()
case "argocd-applicationset-controller":
command = applicationset.NewCommand()
case "argocd-k8s-auth":
command = k8sauth.NewCommand()
default:
command = cli.NewCommand()
}

3
go.mod
View file

@ -12,6 +12,7 @@ require (
github.com/argoproj/gitops-engine v0.6.1-0.20220328190556-73bcea9c8c8f
github.com/argoproj/notifications-engine v0.3.1-0.20220322174744-ac18ca10234c
github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0
github.com/aws/aws-sdk-go v1.38.49
github.com/bombsimon/logrusr/v2 v2.0.1
github.com/bradleyfalzon/ghinstallation/v2 v2.0.4
github.com/casbin/casbin/v2 v2.39.1
@ -228,6 +229,8 @@ require (
sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect
)
require github.com/jmespath/go-jmespath v0.4.0 // indirect
replace (
// https://github.com/golang/go/issues/33546#issuecomment-519656923
github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127

3
go.sum
View file

@ -167,6 +167,7 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.33.16/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go v1.38.49 h1:E31vxjCe6a5I+mJLmUGaZobiWmg9KdWaud9IfceYeYQ=
github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
@ -664,7 +665,9 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=

View file

@ -1 +0,0 @@
150e93a612564c0188a7b953661b44425aa94a28cd73dc393f3639d0a6039add awscli-linux-amd64-v2.4.6.zip

View file

@ -1 +0,0 @@
095f5895976155ec570ea550ad81f92b88f1d55f1d7fc8813b30f329a82a83ba awscli-linux-arm64-v2.4.6.zip

View file

@ -1,23 +0,0 @@
#!/bin/bash
set -eux -o pipefail
. $(dirname $0)/../tool-versions.sh
case $ARCHITECTURE in
arm64|arm|aarch64)
export TARGET_FILE=awscli-linux-${ARCHITECTURE}-v${awscliv2_version}.zip
[ -e ${DOWNLOADS}/${TARGET_FILE} ] || curl -sLf --retry 3 -o ${DOWNLOADS}/${TARGET_FILE} https://awscli.amazonaws.com/awscli-exe-linux-aarch64-$awscliv2_version.zip
$(dirname $0)/compare-chksum.sh
mkdir -p /tmp/awscliv2 && unzip $DOWNLOADS/${TARGET_FILE} -d /tmp/awscliv2
sudo /tmp/awscliv2/aws/install
aws --version
;;
*)
export TARGET_FILE=awscli-linux-${ARCHITECTURE}-v${awscliv2_version}.zip
[ -e ${DOWNLOADS}/${TARGET_FILE} ] || curl -sLf --retry 3 -o ${DOWNLOADS}/${TARGET_FILE} https://awscli.amazonaws.com/awscli-exe-linux-x86_64-$awscliv2_version.zip
$(dirname $0)/compare-chksum.sh
mkdir -p /tmp/awscliv2 && unzip $DOWNLOADS/${TARGET_FILE} -d /tmp/awscliv2
sudo /tmp/awscliv2/aws/install
aws --version
;;
esac

View file

@ -2392,7 +2392,7 @@ func (c *Cluster) RawRestConfig() *rest.Config {
CAData: c.Config.TLSClientConfig.CAData,
}
if c.Config.AWSAuthConfig != nil {
args := []string{"eks", "get-token", "--cluster-name", c.Config.AWSAuthConfig.ClusterName}
args := []string{"aws", "--cluster-name", c.Config.AWSAuthConfig.ClusterName}
if c.Config.AWSAuthConfig.RoleARN != "" {
args = append(args, "--role-arn", c.Config.AWSAuthConfig.RoleARN)
}
@ -2400,8 +2400,8 @@ func (c *Cluster) RawRestConfig() *rest.Config {
Host: c.Server,
TLSClientConfig: tlsClientConfig,
ExecProvider: &api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
Command: "aws",
APIVersion: "client.authentication.k8s.io/v1beta1",
Command: "argocd-k8s-auth",
Args: args,
InteractiveMode: api.NeverExecInteractiveMode,
},