From a189a7d3ecfb9360cb6811f7e92236a1c9dadf9a Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Thu, 15 Aug 2024 16:12:59 -0400 Subject: [PATCH 01/12] AGENT-950: Implement Separate JWT Tokens for Different User Personas - Create 3 seperate JWT tokens- AGENT_AUTH_TOKEN, USER_AUTH_TOKEN, WATCHER_AUTH_TOKEN - Update the claim to set 'auth_scheme' to identify the user persona - Assisted service checks the `auth_scheme` to determine which user persona is allowed to access an endpoint - WATCHER_AUTH_TOKEN is used with header `Watcher-Authorization` and is used by wait-for command ( watcher persona) - USER_AUTH_TOKEN is used with header `Authorization` and is used by curl API requests, systemd services ( user persona) - AGENT_AUTH_TOKEN is used with header `X-Secret-Key` and is used by agent service ( agent persona) --- data/data/agent/files/usr/local/bin/common.sh | 9 +-- .../agent/files/usr/local/bin/start-agent.sh | 2 +- .../local/bin/start-cluster-installation.sh | 8 +-- .../local/bin/wait-for-assisted-service.sh | 2 +- .../assisted-service.env.template | 4 +- .../units/agent-auth-token-status.service | 2 +- .../agent-import-cluster.service.template | 2 +- .../agent-register-cluster.service.template | 2 +- .../agent-register-infraenv.service.template | 2 +- .../systemd/units/apply-host-config.service | 2 +- pkg/agent/cluster.go | 8 +-- pkg/agent/rest.go | 6 +- pkg/asset/agent/gencrypto/auth_utils.go | 24 +++++-- pkg/asset/agent/gencrypto/auth_utils_test.go | 4 +- pkg/asset/agent/gencrypto/authconfig.go | 66 ++++++++++++++----- pkg/asset/agent/gencrypto/authconfig_test.go | 22 +++++++ pkg/asset/agent/image/agentimage.go | 2 +- pkg/asset/agent/image/ignition.go | 30 +++++---- 18 files changed, 136 insertions(+), 61 deletions(-) diff --git a/data/data/agent/files/usr/local/bin/common.sh b/data/data/agent/files/usr/local/bin/common.sh index 39ec1110e66..4b58aede80c 100644 --- a/data/data/agent/files/usr/local/bin/common.sh +++ b/data/data/agent/files/usr/local/bin/common.sh @@ -3,13 +3,14 @@ curl_assisted_service() { local endpoint=$1 local method=${2:-GET} - local additional_options=("${@:3}") # Capture all arguments starting from the third one + local authz=${3:-} + local additional_options=("${@:4}") # Capture all arguments starting from the fourth one local baseURL="${SERVICE_BASE_URL}api/assisted-install/v2" case "${method}" in "POST") curl -s -S -X POST "${additional_options[@]}" "${baseURL}${endpoint}" \ - -H "Authorization: ${AGENT_AUTH_TOKEN}" \ + -H "Authorization: ${authz}" \ -H "accept: application/json" \ -H "Content-Type: application/json" \ ;; @@ -21,8 +22,8 @@ curl_assisted_service() { ;; "GET") curl -s -S -X GET "${additional_options[@]}" "${baseURL}${endpoint}" \ - -H "Authorization: ${AGENT_AUTH_TOKEN}" \ + -H "Authorization: ${authz}" \ -H "Accept: application/json" ;; esac -} +} diff --git a/data/data/agent/files/usr/local/bin/start-agent.sh b/data/data/agent/files/usr/local/bin/start-agent.sh index 4efcbb3f9bb..35715b8c375 100644 --- a/data/data/agent/files/usr/local/bin/start-agent.sh +++ b/data/data/agent/files/usr/local/bin/start-agent.sh @@ -8,7 +8,7 @@ INFRA_ENV_ID="" until [[ $INFRA_ENV_ID != "" && $INFRA_ENV_ID != "null" ]]; do sleep 5 >&2 echo "Querying assisted-service for infra-env-id..." - INFRA_ENV_ID=$(curl_assisted_service "/infra-envs" GET | jq -r .[0].id) + INFRA_ENV_ID=$(curl_assisted_service "/infra-envs" GET $USER_AUTH_TOKEN | jq -r '.[0].id') done echo "Fetched infra-env-id and found: $INFRA_ENV_ID" diff --git a/data/data/agent/files/usr/local/bin/start-cluster-installation.sh b/data/data/agent/files/usr/local/bin/start-cluster-installation.sh index cc614c3cf14..dfe56791d45 100644 --- a/data/data/agent/files/usr/local/bin/start-cluster-installation.sh +++ b/data/data/agent/files/usr/local/bin/start-cluster-installation.sh @@ -10,7 +10,7 @@ cluster_id="" while [[ "${cluster_id}" = "" ]] do # Get cluster id - cluster_id=$(curl_assisted_service "/clusters" GET | jq -r .[].id) + cluster_id=$(curl_assisted_service "/clusters" GET $USER_AUTH_TOKEN | jq -r .[].id) if [[ "${cluster_id}" = "" ]]; then sleep 2 fi @@ -28,7 +28,7 @@ status_issue="90_start-install" num_known_hosts() { local known_hosts=0 local insufficient_hosts=0 - host_status=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET | jq -r .[].status) + host_status=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET $USER_AUTH_TOKEN | jq -r .[].status) if [[ -n ${host_status} ]]; then for status in ${host_status}; do if [[ "${status}" == "known" ]]; then @@ -58,7 +58,7 @@ clear_issue "${status_issue}" while [[ "${cluster_status}" != "installed" ]] do sleep 5 - cluster_info="$(curl_assisted_service "/clusters" GET)" + cluster_info="$(curl_assisted_service "/clusters" GET $USER_AUTH_TOKEN)" cluster_status=$(printf '%s' "${cluster_info}" | jq -r .[].status) echo "Cluster status: ${cluster_status}" 1>&2 # Start the cluster install, if it transitions back to Ready due to a failure, @@ -66,7 +66,7 @@ do case "${cluster_status}" in "ready") echo "Starting cluster installation..." 1>&2 - res=$(curl_assisted_service "/clusters/${cluster_id}/actions/install" POST -w "%{http_code}" -o /dev/null) + res=$(curl_assisted_service "/clusters/${cluster_id}/actions/install" POST $USER_AUTH_TOKEN -w "%{http_code}" -o /dev/null) if [[ $res = "202" ]]; then printf '\nCluster installation started\n' 1>&2 fi diff --git a/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh b/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh index d68b63835d7..711477adb26 100644 --- a/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh +++ b/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh @@ -6,7 +6,7 @@ source "common.sh" echo "Waiting for assisted-service to be ready" -until curl_assisted_service "/infra-envs" GET -o /dev/null --silent --fail; do +until curl_assisted_service "/infra-envs" GET $USER_AUTH_TOKEN -o /dev/null --silent --fail; do printf '.' sleep 5 done diff --git a/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template b/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template index f401eea149c..37be1de480a 100644 --- a/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template +++ b/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template @@ -20,4 +20,6 @@ OPENSHIFT_INSTALL_RELEASE_IMAGE_MIRROR={{.ReleaseImageMirror}} STORAGE=filesystem INFRA_ENV_ID={{.InfraEnvID}} EC_PUBLIC_KEY_PEM={{.PublicKeyPEM}} -AGENT_AUTH_TOKEN={{.Token}} +AGENT_AUTH_TOKEN={{.AgentAuthToken}} +USER_AUTH_TOKEN={{.UserAuthToken}} +WATCHER_AUTH_TOKEN={{.WatcherAuthToken}} diff --git a/data/data/agent/systemd/units/agent-auth-token-status.service b/data/data/agent/systemd/units/agent-auth-token-status.service index ea985649148..fdeec8de73a 100644 --- a/data/data/agent/systemd/units/agent-auth-token-status.service +++ b/data/data/agent/systemd/units/agent-auth-token-status.service @@ -1,5 +1,5 @@ [Unit] -Description=service that displays a message if agent auth token is expired. +Description=service that displays a message if auth tokens are expired. Wants=network-online.target After=network-online.target agent-interactive-console.service ConditionPathExists=/etc/assisted/add-nodes.env diff --git a/data/data/agent/systemd/units/agent-import-cluster.service.template b/data/data/agent/systemd/units/agent-import-cluster.service.template index 57923702b40..eeab1719c61 100644 --- a/data/data/agent/systemd/units/agent-import-cluster.service.template +++ b/data/data/agent/systemd/units/agent-import-cluster.service.template @@ -16,7 +16,7 @@ EnvironmentFile=/usr/local/share/assisted-service/assisted-service.env EnvironmentFile=/etc/assisted/add-nodes.env ExecStartPre=/bin/rm -f %t/%n.ctr-id ExecStartPre=/usr/local/bin/wait-for-assisted-service.sh -ExecStart=podman run --net host --cidfile=%t/%n.ctr-id --cgroups=no-conmon --log-driver=journald --rm --pod-id-file=%t/assisted-service-pod.pod-id --replace --name=agent-import-cluster -v /etc/assisted/clusterconfig:/clusterconfig -v /etc/assisted/manifests:/manifests -v /etc/assisted/extra-manifests:/extra-manifests {{ if .HaveMirrorConfig }}-v /etc/containers:/etc/containers{{ end }} {{.CaBundleMount}} --env SERVICE_BASE_URL --env OPENSHIFT_INSTALL_RELEASE_IMAGE_MIRROR --env CLUSTER_ID --env CLUSTER_NAME --env CLUSTER_API_VIP_DNS_NAME --env AGENT_AUTH_TOKEN $SERVICE_IMAGE /usr/local/bin/agent-installer-client importCluster +ExecStart=podman run --net host --cidfile=%t/%n.ctr-id --cgroups=no-conmon --log-driver=journald --rm --pod-id-file=%t/assisted-service-pod.pod-id --replace --name=agent-import-cluster -v /etc/assisted/clusterconfig:/clusterconfig -v /etc/assisted/manifests:/manifests -v /etc/assisted/extra-manifests:/extra-manifests {{ if .HaveMirrorConfig }}-v /etc/containers:/etc/containers{{ end }} {{.CaBundleMount}} --env SERVICE_BASE_URL --env OPENSHIFT_INSTALL_RELEASE_IMAGE_MIRROR --env CLUSTER_ID --env CLUSTER_NAME --env CLUSTER_API_VIP_DNS_NAME --env USER_AUTH_TOKEN $SERVICE_IMAGE /usr/local/bin/agent-installer-client importCluster ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id diff --git a/data/data/agent/systemd/units/agent-register-cluster.service.template b/data/data/agent/systemd/units/agent-register-cluster.service.template index 11c01bf2d26..1c5e400c58e 100644 --- a/data/data/agent/systemd/units/agent-register-cluster.service.template +++ b/data/data/agent/systemd/units/agent-register-cluster.service.template @@ -15,7 +15,7 @@ EnvironmentFile=/usr/local/share/assisted-service/agent-images.env EnvironmentFile=/usr/local/share/assisted-service/assisted-service.env ExecStartPre=/bin/rm -f %t/%n.ctr-id ExecStartPre=/usr/local/bin/wait-for-assisted-service.sh -ExecStart=podman run --net host --cidfile=%t/%n.ctr-id --cgroups=no-conmon --log-driver=journald --rm --pod-id-file=%t/assisted-service-pod.pod-id --replace --name=agent-register-cluster -v /etc/assisted/manifests:/manifests -v /etc/assisted/extra-manifests:/extra-manifests {{ if .HaveMirrorConfig }}-v /etc/containers:/etc/containers{{ end }} {{.CaBundleMount}} --env SERVICE_BASE_URL --env OPENSHIFT_INSTALL_RELEASE_IMAGE_MIRROR --env AGENT_AUTH_TOKEN $SERVICE_IMAGE /usr/local/bin/agent-installer-client registerCluster +ExecStart=podman run --net host --cidfile=%t/%n.ctr-id --cgroups=no-conmon --log-driver=journald --rm --pod-id-file=%t/assisted-service-pod.pod-id --replace --name=agent-register-cluster -v /etc/assisted/manifests:/manifests -v /etc/assisted/extra-manifests:/extra-manifests {{ if .HaveMirrorConfig }}-v /etc/containers:/etc/containers{{ end }} {{.CaBundleMount}} --env SERVICE_BASE_URL --env OPENSHIFT_INSTALL_RELEASE_IMAGE_MIRROR --env USER_AUTH_TOKEN $SERVICE_IMAGE /usr/local/bin/agent-installer-client registerCluster ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id diff --git a/data/data/agent/systemd/units/agent-register-infraenv.service.template b/data/data/agent/systemd/units/agent-register-infraenv.service.template index f6c399d9127..e4698d2a26d 100644 --- a/data/data/agent/systemd/units/agent-register-infraenv.service.template +++ b/data/data/agent/systemd/units/agent-register-infraenv.service.template @@ -12,7 +12,7 @@ EnvironmentFile=/etc/assisted/rendezvous-host.env EnvironmentFile=/usr/local/share/assisted-service/agent-images.env EnvironmentFile=/usr/local/share/assisted-service/assisted-service.env ExecStartPre=/bin/rm -f %t/%n.ctr-id -ExecStart=podman run --net host --cidfile=%t/%n.ctr-id --cgroups=no-conmon --log-driver=journald --rm --pod-id-file=%t/assisted-service-pod.pod-id --replace --name=agent-register-infraenv -v /etc/assisted/manifests:/manifests --env SERVICE_BASE_URL --env IMAGE_TYPE_ISO --env AGENT_AUTH_TOKEN $SERVICE_IMAGE /usr/local/bin/agent-installer-client registerInfraEnv +ExecStart=podman run --net host --cidfile=%t/%n.ctr-id --cgroups=no-conmon --log-driver=journald --rm --pod-id-file=%t/assisted-service-pod.pod-id --replace --name=agent-register-infraenv -v /etc/assisted/manifests:/manifests --env SERVICE_BASE_URL --env IMAGE_TYPE_ISO --env USER_AUTH_TOKEN $SERVICE_IMAGE /usr/local/bin/agent-installer-client registerInfraEnv ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id diff --git a/data/data/agent/systemd/units/apply-host-config.service b/data/data/agent/systemd/units/apply-host-config.service index a79442c39fa..1c993b20089 100644 --- a/data/data/agent/systemd/units/apply-host-config.service +++ b/data/data/agent/systemd/units/apply-host-config.service @@ -14,7 +14,7 @@ EnvironmentFile=/usr/local/share/assisted-service/assisted-service.env ExecStartPre=/bin/rm -f %t/%n.ctr-id ExecStartPre=/bin/mkdir -p %t/agent-installer /etc/assisted/hostconfig ExecStartPre=/usr/local/bin/wait-for-assisted-service.sh -ExecStart=podman run --net host --cidfile=%t/%n.ctr-id --cgroups=no-conmon --log-driver=journald --restart=on-failure:10 --pod-id-file=%t/assisted-service-pod.pod-id --replace --name=apply-host-config -v /etc/assisted/hostconfig:/etc/assisted/hostconfig -v %t/agent-installer:/var/run/agent-installer:z --env SERVICE_BASE_URL --env INFRA_ENV_ID --env WORKFLOW_TYPE --env AGENT_AUTH_TOKEN $SERVICE_IMAGE /usr/local/bin/agent-installer-client configure +ExecStart=podman run --net host --cidfile=%t/%n.ctr-id --cgroups=no-conmon --log-driver=journald --restart=on-failure:10 --pod-id-file=%t/assisted-service-pod.pod-id --replace --name=apply-host-config -v /etc/assisted/hostconfig:/etc/assisted/hostconfig -v %t/agent-installer:/var/run/agent-installer:z --env SERVICE_BASE_URL --env INFRA_ENV_ID --env WORKFLOW_TYPE --env USER_AUTH_TOKEN $SERVICE_IMAGE /usr/local/bin/agent-installer-client configure ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id diff --git a/pkg/agent/cluster.go b/pkg/agent/cluster.go index 6ff0d908790..f190870efd2 100644 --- a/pkg/agent/cluster.go +++ b/pkg/agent/cluster.go @@ -69,17 +69,17 @@ func NewCluster(ctx context.Context, assetDir, rendezvousIP, kubeconfigPath, ssh czero := &Cluster{} capi := &clientSet{} - var authToken string + var watcherAuthToken string var err error switch workflowType { case workflow.AgentWorkflowTypeInstall: - authToken, err = FindAuthTokenFromAssetStore(assetDir) + watcherAuthToken, err = FindAuthTokenFromAssetStore(assetDir) if err != nil { return nil, err } case workflow.AgentWorkflowTypeAddNodes: - authToken, err = gencrypto.GetAuthTokenFromCluster(ctx, kubeconfigPath) + watcherAuthToken, err = gencrypto.GetAuthTokenFromCluster(ctx, kubeconfigPath) if err != nil { return nil, err } @@ -87,7 +87,7 @@ func NewCluster(ctx context.Context, assetDir, rendezvousIP, kubeconfigPath, ssh return nil, fmt.Errorf("AgentWorkflowType value not supported: %s", workflowType) } - restclient := NewNodeZeroRestClient(ctx, rendezvousIP, sshKey, authToken) + restclient := NewNodeZeroRestClient(ctx, rendezvousIP, sshKey, watcherAuthToken) kubeclient, err := NewClusterKubeAPIClient(ctx, kubeconfigPath) if err != nil { diff --git a/pkg/agent/rest.go b/pkg/agent/rest.go index 4388f5f49f4..b264e7d1303 100644 --- a/pkg/agent/rest.go +++ b/pkg/agent/rest.go @@ -33,7 +33,7 @@ type NodeZeroRestClient struct { } // NewNodeZeroRestClient Initialize a new rest client to interact with the Agent Rest API on node zero. -func NewNodeZeroRestClient(ctx context.Context, rendezvousIP, sshKey, token string) *NodeZeroRestClient { +func NewNodeZeroRestClient(ctx context.Context, rendezvousIP, sshKey, watcherAuthToken string) *NodeZeroRestClient { restClient := &NodeZeroRestClient{} // Get SSH Keys which can be used to determine if Rest API failures are due to network connectivity issues @@ -48,7 +48,7 @@ func NewNodeZeroRestClient(ctx context.Context, rendezvousIP, sshKey, token stri Path: client.DefaultBasePath, } - config.AuthInfo = gencrypto.UserAuthHeaderWriter(token) + config.AuthInfo = gencrypto.WatcherAuthHeaderWriter(watcherAuthToken) client := client.New(config) @@ -137,7 +137,7 @@ func FindAuthTokenFromAssetStore(assetDir string) (string, error) { var authToken string if authConfig != nil { - authToken = authConfig.(*gencrypto.AuthConfig).AgentAuthToken + authToken = authConfig.(*gencrypto.AuthConfig).WatcherAuthToken } return authToken, nil diff --git a/pkg/asset/agent/gencrypto/auth_utils.go b/pkg/asset/agent/gencrypto/auth_utils.go index 13628045e9d..e28a19cf060 100644 --- a/pkg/asset/agent/gencrypto/auth_utils.go +++ b/pkg/asset/agent/gencrypto/auth_utils.go @@ -9,22 +9,32 @@ import ( "github.com/pkg/errors" ) -// UserAuthHeaderWriter sets the JWT authorization token. -func UserAuthHeaderWriter(token string) runtime.ClientAuthInfoWriter { +// WatcherAuthHeaderWriter sets the JWT authorization token. +func WatcherAuthHeaderWriter(token string) runtime.ClientAuthInfoWriter { return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error { - return r.SetHeaderParam("Authorization", token) + return r.SetHeaderParam("Watcher-Authorization", token) }) } -// ParseExpirationFromToken checks if the token is expired or not. -func ParseExpirationFromToken(tokenString string) (time.Time, error) { +// ParseToken checks if the token string is valid or not and returns JWT token claim. +func ParseToken(tokenString string) (jwt.MapClaims, error) { token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{}) if err != nil { - return time.Time{}, err + return nil, err } claims, ok := token.Claims.(jwt.MapClaims) if !ok { - return time.Time{}, errors.Errorf("malformed token claims in url") + return nil, errors.Errorf("malformed token claims in url") + } + return claims, nil +} + + +// ParseExpirationFromToken checks if the token is expired or not. +func ParseExpirationFromToken(tokenString string) (time.Time, error) { + claims, err := ParseToken(tokenString) + if err != nil { + return time.Time{}, err } exp, ok := claims["exp"].(float64) if !ok { diff --git a/pkg/asset/agent/gencrypto/auth_utils_test.go b/pkg/asset/agent/gencrypto/auth_utils_test.go index e8c24502b8c..903b2570ff5 100644 --- a/pkg/asset/agent/gencrypto/auth_utils_test.go +++ b/pkg/asset/agent/gencrypto/auth_utils_test.go @@ -13,12 +13,12 @@ func TestParseExpirationFromToken(t *testing.T) { assert.NotEmpty(t, privateKey) assert.NoError(t, err) - tokenNoExp, err := generateToken(privateKey, nil) + tokenNoExp, err := generateToken("userAuth", privateKey, nil) assert.NotEmpty(t, tokenNoExp) assert.NoError(t, err) expiry := time.Now().UTC().Add(30 * time.Second) - tokenWithExp, err := generateToken(privateKey, &expiry) + tokenWithExp, err := generateToken("userAuth", privateKey, &expiry) assert.NotEmpty(t, tokenWithExp) assert.NoError(t, err) diff --git a/pkg/asset/agent/gencrypto/authconfig.go b/pkg/asset/agent/gencrypto/authconfig.go index 1a72b9b3b0c..5c5222c5d70 100644 --- a/pkg/asset/agent/gencrypto/authconfig.go +++ b/pkg/asset/agent/gencrypto/authconfig.go @@ -34,11 +34,16 @@ var ( ) // AuthType holds the authenticator type for agent based installer. -const AuthType = "agent-installer-local" +const ( + AuthType = "agent-installer-local" + agentPersona = "agentAuth" + userPersona = "userAuth" + watcherPersona = "watcherAuth" +) // AuthConfig is an asset that generates ECDSA public/private keys, JWT token. type AuthConfig struct { - PublicKey, AgentAuthToken, AgentAuthTokenExpiry, AuthType string + PublicKey, AgentAuthToken, UserAuthToken, WatcherAuthToken, AuthTokenExpiry, AuthType string } var _ asset.Asset = (*AuthConfig)(nil) @@ -69,23 +74,49 @@ func (a *AuthConfig) Generate(_ context.Context, dependencies asset.Parents) err switch agentWorkflow.Workflow { case workflow.AgentWorkflowTypeInstall: // Auth tokens do not expire - token, err := generateToken(privateKey, nil) + agentAuthToken, err := generateToken(agentPersona, privateKey, nil) + if err != nil { + return err + } + a.AgentAuthToken = agentAuthToken + + userAuthToken, err := generateToken(userPersona, privateKey, nil) if err != nil { return err } - a.AgentAuthToken = token + a.UserAuthToken = userAuthToken + + watcherAuthToken, err := generateToken(watcherPersona, privateKey, nil) + if err != nil { + return err + } + a.WatcherAuthToken = watcherAuthToken + case workflow.AgentWorkflowTypeAddNodes: addNodesConfig := &joiner.AddNodesConfig{} dependencies.Get(addNodesConfig) // Auth tokens expires after 48 hours expiry := time.Now().UTC().Add(48 * time.Hour) - a.AgentAuthTokenExpiry = expiry.Format(time.RFC3339) - token, err := generateToken(privateKey, &expiry) + a.AuthTokenExpiry = expiry.Format(time.RFC3339) + + agentAuthToken, err := generateToken(agentPersona, privateKey, &expiry) if err != nil { return err } - a.AgentAuthToken = token + a.AgentAuthToken = agentAuthToken + + userAuthToken, err := generateToken(userPersona, privateKey, &expiry) + if err != nil { + return err + } + a.UserAuthToken = userAuthToken + + watcherAuthToken, err := generateToken(watcherPersona, privateKey, &expiry) + if err != nil { + return err + } + a.WatcherAuthToken = watcherAuthToken err = a.createOrUpdateAuthTokenSecret(addNodesConfig.Params.Kubeconfig) if err != nil { @@ -147,10 +178,11 @@ func keyPairPEM() (string, string, error) { } // generateToken returns a JWT token based on the private key. -func generateToken(privateKkeyPem string, expiry *time.Time) (string, error) { +func generateToken(userPersona string, privateKeyPem string, expiry *time.Time) (string, error) { // Create the JWT claims - claims := jwt.MapClaims{} - + claims := jwt.MapClaims{ + "sub": userPersona, + } // Set the expiry time if provided if expiry != nil { claims["exp"] = expiry.Unix() @@ -159,7 +191,7 @@ func generateToken(privateKkeyPem string, expiry *time.Time) (string, error) { // Create the token using the ES256 signing method and the claims token := jwt.NewWithClaims(jwt.SigningMethodES256, claims) - priv, err := jwt.ParseECPrivateKeyFromPEM([]byte(privateKkeyPem)) + priv, err := jwt.ParseECPrivateKeyFromPEM([]byte(privateKeyPem)) if err != nil { return "", err } @@ -229,7 +261,7 @@ func (a *AuthConfig) createOrUpdateAuthTokenSecret(kubeconfigPath string) error // Update the token in asset store with the retrieved token from the cluster a.AgentAuthToken = retrievedToken // get the token expiry time of the retrieved token from the cluster - a.AgentAuthTokenExpiry = expiryTime.UTC().Format(time.RFC3339) + a.AuthTokenExpiry = expiryTime.UTC().Format(time.RFC3339) retrievedPublicKey, err := extractPublicKeyFromSecret(retrievedSecret) if err != nil { @@ -237,7 +269,7 @@ func (a *AuthConfig) createOrUpdateAuthTokenSecret(kubeconfigPath string) error } // Update the asset store with the retrieved public key associated with the valid token from the cluster a.PublicKey = retrievedPublicKey - logrus.Infof("Reusing existing auth token (valid up to %s)", a.AgentAuthTokenExpiry) + logrus.Infof("Reusing existing auth token (valid up to %s)", a.AuthTokenExpiry) } return err } @@ -250,7 +282,7 @@ func (a *AuthConfig) createSecret(k8sclientset kubernetes.Interface) error { // only for informational purposes Annotations: map[string]string{ "updatedAt": "", // Initially set to empty - "expiresAt": a.AgentAuthTokenExpiry, + "expiresAt": a.AuthTokenExpiry, }, }, Type: corev1.SecretTypeOpaque, @@ -263,7 +295,7 @@ func (a *AuthConfig) createSecret(k8sclientset kubernetes.Interface) error { if err != nil { return fmt.Errorf("failed to create secret: %w", err) } - logrus.Infof("Generated auth token (valid up to %s)", a.AgentAuthTokenExpiry) + logrus.Infof("Generated auth token (valid up to %s)", a.AuthTokenExpiry) logrus.Infof("Created secret %s/%s", authTokenSecretNamespace, authTokenSecretName) return nil @@ -274,13 +306,13 @@ func (a *AuthConfig) refreshAuthTokenSecret(k8sclientset kubernetes.Interface, r retrievedSecret.Data[authTokenPublicDataKey] = []byte(a.PublicKey) // only for informational purposes retrievedSecret.Annotations["updatedAt"] = time.Now().UTC().Format(time.RFC3339) - retrievedSecret.Annotations["expiresAt"] = a.AgentAuthTokenExpiry + retrievedSecret.Annotations["expiresAt"] = a.AuthTokenExpiry _, err := k8sclientset.CoreV1().Secrets(authTokenSecretNamespace).Update(context.TODO(), retrievedSecret, metav1.UpdateOptions{}) if err != nil { return err } - logrus.Infof("Auth token regenerated (valid up to %s)", a.AgentAuthTokenExpiry) + logrus.Infof("Auth token regenerated (valid up to %s)", a.AuthTokenExpiry) logrus.Infof("Updated secret %s/%s", authTokenSecretNamespace, authTokenSecretName) return nil } diff --git a/pkg/asset/agent/gencrypto/authconfig_test.go b/pkg/asset/agent/gencrypto/authconfig_test.go index 0bb1aec08e2..7a0fe032df8 100644 --- a/pkg/asset/agent/gencrypto/authconfig_test.go +++ b/pkg/asset/agent/gencrypto/authconfig_test.go @@ -31,6 +31,28 @@ func TestAuthConfig_Generate(t *testing.T) { assert.NoError(t, err) assert.NotEmpty(t, authConfigAsset.PublicKey) assert.NotEmpty(t, authConfigAsset.AgentAuthToken) + + // All the 3 tokens should be unique + assert.NotEqual(t, authConfigAsset.AgentAuthToken, authConfigAsset.UserAuthToken) + assert.NotEqual(t, authConfigAsset.AgentAuthToken, authConfigAsset.WatcherAuthToken) + assert.NotEqual(t, authConfigAsset.UserAuthToken, authConfigAsset.WatcherAuthToken) + + // verify each token is signed with correct persona + claims , err := ParseToken(authConfigAsset.AgentAuthToken) + assert.NoError(t, err) + persona, _ := claims["sub"].(string) + assert.Equal(t, persona, agentPersona) + + claims , err = ParseToken(authConfigAsset.UserAuthToken) + assert.NoError(t, err) + persona, _ = claims["sub"].(string) + assert.Equal(t, persona, userPersona) + + claims , err = ParseToken(authConfigAsset.WatcherAuthToken) + assert.NoError(t, err) + persona, _ = claims["sub"].(string) + assert.Equal(t, persona, watcherPersona) + }) } } diff --git a/pkg/asset/agent/image/agentimage.go b/pkg/asset/agent/image/agentimage.go index fa23404c2d5..3f6a043447a 100644 --- a/pkg/asset/agent/image/agentimage.go +++ b/pkg/asset/agent/image/agentimage.go @@ -80,7 +80,7 @@ func (a *AgentImage) Generate(ctx context.Context, dependencies asset.Parents) e a.platform = clusterInfo.PlatformType a.isoFilename = agentAddNodesISOFilename - a.imageExpiresAt = authConfig.AgentAuthTokenExpiry + a.imageExpiresAt = authConfig.AuthTokenExpiry default: return fmt.Errorf("AgentWorkflowType value not supported: %s", agentWorkflow.Workflow) diff --git a/pkg/asset/agent/image/ignition.go b/pkg/asset/agent/image/ignition.go index 723d0766a0f..42f88e124fb 100644 --- a/pkg/asset/agent/image/ignition.go +++ b/pkg/asset/agent/image/ignition.go @@ -78,7 +78,9 @@ type agentTemplateData struct { ConfigImageFiles string ImageTypeISO string PublicKeyPEM string - Token string + AgentAuthToken string + UserAuthToken string + WatcherAuthToken string TokenExpiry string AuthType string CaBundleMount string @@ -205,7 +207,7 @@ func (a *Ignition) Generate(ctx context.Context, dependencies asset.Parents) err // Enable add-nodes specific services enabledServices = append(enabledServices, "agent-add-node.service") // Generate add-nodes.env file - addNodesEnvFile := ignition.FileFromString(addNodesEnvPath, "root", 0644, getAddNodesEnv(*clusterInfo, authConfig.AgentAuthTokenExpiry)) + addNodesEnvFile := ignition.FileFromString(addNodesEnvPath, "root", 0644, getAddNodesEnv(*clusterInfo, authConfig.AuthTokenExpiry)) config.Storage.Files = append(config.Storage.Files, addNodesEnvFile) // Enable auth token service @@ -283,7 +285,9 @@ func (a *Ignition) Generate(ctx context.Context, dependencies asset.Parents) err authConfig.PublicKey, authConfig.AuthType, authConfig.AgentAuthToken, - authConfig.AgentAuthTokenExpiry, + authConfig.UserAuthToken, + authConfig.WatcherAuthToken, + authConfig.AuthTokenExpiry, caBundleMount, len(registriesConfig.MirrorConfig) > 0, numMasters, numWorkers, @@ -298,7 +302,7 @@ func (a *Ignition) Generate(ctx context.Context, dependencies asset.Parents) err rendezvousHostFile := ignition.FileFromString(rendezvousHostEnvPath, "root", 0644, - getRendezvousHostEnv(agentTemplateData.ServiceProtocol, a.RendezvousIP, authConfig.AgentAuthToken, agentWorkflow.Workflow)) + getRendezvousHostEnv(agentTemplateData.ServiceProtocol, a.RendezvousIP, authConfig.AgentAuthToken, authConfig.UserAuthToken, agentWorkflow.Workflow)) config.Storage.Files = append(config.Storage.Files, rendezvousHostFile) err = addBootstrapScripts(&config, agentManifests.ClusterImageSet.Spec.ReleaseImage) @@ -404,7 +408,7 @@ func addBootstrapScripts(config *igntypes.Config, releaseImage string) (err erro } func getTemplateData(name, pullSecret, releaseImageList, releaseImage, releaseImageMirror, publicContainerRegistries, - imageTypeISO, infraEnvID, publicKey, authType, token, tokenExpiry, caBundleMount string, + imageTypeISO, infraEnvID, publicKey, authType, agentAuthToken, userAuthToken, watcherAuthToken, tokenExpiry, caBundleMount string, haveMirrorConfig bool, numMasters, numWorkers int, osImage *models.OsImage, @@ -426,13 +430,15 @@ func getTemplateData(name, pullSecret, releaseImageList, releaseImage, releaseIm ImageTypeISO: imageTypeISO, PublicKeyPEM: publicKey, AuthType: authType, - Token: token, + AgentAuthToken: agentAuthToken, + UserAuthToken: userAuthToken, + WatcherAuthToken: watcherAuthToken, TokenExpiry: tokenExpiry, CaBundleMount: caBundleMount, } } -func getRendezvousHostEnv(serviceProtocol, nodeZeroIP, token string, workflowType workflow.AgentWorkflowType) string { +func getRendezvousHostEnv(serviceProtocol, nodeZeroIP, agentAuthtoken, userAuthToken string, workflowType workflow.AgentWorkflowType) string { serviceBaseURL := url.URL{ Scheme: serviceProtocol, Host: net.JoinHostPort(nodeZeroIP, "8090"), @@ -443,8 +449,10 @@ func getRendezvousHostEnv(serviceProtocol, nodeZeroIP, token string, workflowTyp Host: net.JoinHostPort(nodeZeroIP, "8888"), Path: "/", } - // AGENT_AUTH_TOKEN is required to authenticate API requests against agent-installer-local auth type. - // PULL_SECRET_TOKEN contains the same value as AGENT_AUTH_TOKEN. The name PULL_SECRET_TOKEN is used in + // USER_AUTH_TOKEN is required to authenticate API requests against agent-installer-local auth type + // and for the endpoints marked with userAuth security definition in assisted-service swagger.yaml. + // PULL_SECRET_TOKEN contains the AGENT_AUTH_TOKEN and is required for the endpoints marked with agentAuth security definition in assisted-service swagger.yaml. + // The name PULL_SECRET_TOKEN is used in // assisted-installer-agent, which is responsible for authenticating API requests related to agents. // Historically, PULL_SECRET_TOKEN was used solely to store the pull secrets. // However, as the authentication mechanisms have evolved, PULL_SECRET_TOKEN now @@ -456,10 +464,10 @@ func getRendezvousHostEnv(serviceProtocol, nodeZeroIP, token string, workflowTyp return fmt.Sprintf(`NODE_ZERO_IP=%s SERVICE_BASE_URL=%s IMAGE_SERVICE_BASE_URL=%s -AGENT_AUTH_TOKEN=%s PULL_SECRET_TOKEN=%s +USER_AUTH_TOKEN=%s WORKFLOW_TYPE=%s -`, nodeZeroIP, serviceBaseURL.String(), imageServiceBaseURL.String(), token, token, workflowType) +`, nodeZeroIP, serviceBaseURL.String(), imageServiceBaseURL.String(), agentAuthtoken, userAuthToken, workflowType) } func getAddNodesEnv(clusterInfo joiner.ClusterInfo, authTokenExpiry string) string { From fe60214c2b21ec4eff697578952dce7df00e4123 Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Mon, 7 Oct 2024 16:10:00 -0400 Subject: [PATCH 02/12] fix linting errors, unit tests, shellchecks --- .../agent/files/usr/local/bin/start-agent.sh | 2 +- .../usr/local/bin/start-cluster-installation.sh | 8 ++++---- .../usr/local/bin/wait-for-assisted-service.sh | 2 +- pkg/asset/agent/gencrypto/auth_utils.go | 1 - pkg/asset/agent/gencrypto/authconfig.go | 8 ++++---- pkg/asset/agent/gencrypto/authconfig_test.go | 16 +++++++++------- pkg/asset/agent/image/ignition_test.go | 17 +++++++++++------ 7 files changed, 30 insertions(+), 24 deletions(-) diff --git a/data/data/agent/files/usr/local/bin/start-agent.sh b/data/data/agent/files/usr/local/bin/start-agent.sh index 35715b8c375..92fdfbb03a0 100644 --- a/data/data/agent/files/usr/local/bin/start-agent.sh +++ b/data/data/agent/files/usr/local/bin/start-agent.sh @@ -8,7 +8,7 @@ INFRA_ENV_ID="" until [[ $INFRA_ENV_ID != "" && $INFRA_ENV_ID != "null" ]]; do sleep 5 >&2 echo "Querying assisted-service for infra-env-id..." - INFRA_ENV_ID=$(curl_assisted_service "/infra-envs" GET $USER_AUTH_TOKEN | jq -r '.[0].id') + INFRA_ENV_ID=$(curl_assisted_service "/infra-envs" GET "$USER_AUTH_TOKEN" | jq -r '.[0].id') done echo "Fetched infra-env-id and found: $INFRA_ENV_ID" diff --git a/data/data/agent/files/usr/local/bin/start-cluster-installation.sh b/data/data/agent/files/usr/local/bin/start-cluster-installation.sh index dfe56791d45..48ad90be0e6 100644 --- a/data/data/agent/files/usr/local/bin/start-cluster-installation.sh +++ b/data/data/agent/files/usr/local/bin/start-cluster-installation.sh @@ -10,7 +10,7 @@ cluster_id="" while [[ "${cluster_id}" = "" ]] do # Get cluster id - cluster_id=$(curl_assisted_service "/clusters" GET $USER_AUTH_TOKEN | jq -r .[].id) + cluster_id=$(curl_assisted_service "/clusters" GET "$USER_AUTH_TOKEN" | jq -r .[].id) if [[ "${cluster_id}" = "" ]]; then sleep 2 fi @@ -28,7 +28,7 @@ status_issue="90_start-install" num_known_hosts() { local known_hosts=0 local insufficient_hosts=0 - host_status=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET $USER_AUTH_TOKEN | jq -r .[].status) + host_status=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET "$USER_AUTH_TOKEN" | jq -r .[].status) if [[ -n ${host_status} ]]; then for status in ${host_status}; do if [[ "${status}" == "known" ]]; then @@ -58,7 +58,7 @@ clear_issue "${status_issue}" while [[ "${cluster_status}" != "installed" ]] do sleep 5 - cluster_info="$(curl_assisted_service "/clusters" GET $USER_AUTH_TOKEN)" + cluster_info="$(curl_assisted_service "/clusters" GET "$USER_AUTH_TOKEN")" cluster_status=$(printf '%s' "${cluster_info}" | jq -r .[].status) echo "Cluster status: ${cluster_status}" 1>&2 # Start the cluster install, if it transitions back to Ready due to a failure, @@ -66,7 +66,7 @@ do case "${cluster_status}" in "ready") echo "Starting cluster installation..." 1>&2 - res=$(curl_assisted_service "/clusters/${cluster_id}/actions/install" POST $USER_AUTH_TOKEN -w "%{http_code}" -o /dev/null) + res=$(curl_assisted_service "/clusters/${cluster_id}/actions/install" POST "$USER_AUTH_TOKEN" -w "%{http_code}" -o /dev/null) if [[ $res = "202" ]]; then printf '\nCluster installation started\n' 1>&2 fi diff --git a/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh b/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh index 711477adb26..bf9d65ce675 100644 --- a/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh +++ b/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh @@ -6,7 +6,7 @@ source "common.sh" echo "Waiting for assisted-service to be ready" -until curl_assisted_service "/infra-envs" GET $USER_AUTH_TOKEN -o /dev/null --silent --fail; do +until curl_assisted_service "/infra-envs" GET "$USER_AUTH_TOKEN" -o /dev/null --silent --fail; do printf '.' sleep 5 done diff --git a/pkg/asset/agent/gencrypto/auth_utils.go b/pkg/asset/agent/gencrypto/auth_utils.go index e28a19cf060..366c562c48b 100644 --- a/pkg/asset/agent/gencrypto/auth_utils.go +++ b/pkg/asset/agent/gencrypto/auth_utils.go @@ -29,7 +29,6 @@ func ParseToken(tokenString string) (jwt.MapClaims, error) { return claims, nil } - // ParseExpirationFromToken checks if the token is expired or not. func ParseExpirationFromToken(tokenString string) (time.Time, error) { claims, err := ParseToken(tokenString) diff --git a/pkg/asset/agent/gencrypto/authconfig.go b/pkg/asset/agent/gencrypto/authconfig.go index 5c5222c5d70..384e85d0c7c 100644 --- a/pkg/asset/agent/gencrypto/authconfig.go +++ b/pkg/asset/agent/gencrypto/authconfig.go @@ -35,9 +35,9 @@ var ( // AuthType holds the authenticator type for agent based installer. const ( - AuthType = "agent-installer-local" - agentPersona = "agentAuth" - userPersona = "userAuth" + AuthType = "agent-installer-local" + agentPersona = "agentAuth" + userPersona = "userAuth" watcherPersona = "watcherAuth" ) @@ -99,7 +99,7 @@ func (a *AuthConfig) Generate(_ context.Context, dependencies asset.Parents) err // Auth tokens expires after 48 hours expiry := time.Now().UTC().Add(48 * time.Hour) a.AuthTokenExpiry = expiry.Format(time.RFC3339) - + agentAuthToken, err := generateToken(agentPersona, privateKey, &expiry) if err != nil { return err diff --git a/pkg/asset/agent/gencrypto/authconfig_test.go b/pkg/asset/agent/gencrypto/authconfig_test.go index 7a0fe032df8..298f7f5c0b2 100644 --- a/pkg/asset/agent/gencrypto/authconfig_test.go +++ b/pkg/asset/agent/gencrypto/authconfig_test.go @@ -38,21 +38,23 @@ func TestAuthConfig_Generate(t *testing.T) { assert.NotEqual(t, authConfigAsset.UserAuthToken, authConfigAsset.WatcherAuthToken) // verify each token is signed with correct persona - claims , err := ParseToken(authConfigAsset.AgentAuthToken) + claims, err := ParseToken(authConfigAsset.AgentAuthToken) assert.NoError(t, err) - persona, _ := claims["sub"].(string) + persona, ok := claims["sub"].(string) assert.Equal(t, persona, agentPersona) + assert.Equal(t, ok, true) - claims , err = ParseToken(authConfigAsset.UserAuthToken) + claims, err = ParseToken(authConfigAsset.UserAuthToken) assert.NoError(t, err) - persona, _ = claims["sub"].(string) + persona, ok = claims["sub"].(string) assert.Equal(t, persona, userPersona) + assert.Equal(t, ok, true) - claims , err = ParseToken(authConfigAsset.WatcherAuthToken) + claims, err = ParseToken(authConfigAsset.WatcherAuthToken) assert.NoError(t, err) - persona, _ = claims["sub"].(string) + persona, ok = claims["sub"].(string) assert.Equal(t, persona, watcherPersona) - + assert.Equal(t, ok, true) }) } } diff --git a/pkg/asset/agent/image/ignition_test.go b/pkg/asset/agent/image/ignition_test.go index 2742747ced3..7ffb65fcb0a 100644 --- a/pkg/asset/agent/image/ignition_test.go +++ b/pkg/asset/agent/image/ignition_test.go @@ -93,8 +93,10 @@ func TestIgnition_getTemplateData(t *testing.T) { clusterName := "test-agent-cluster-install.test" publicKey := "-----BEGIN EC PUBLIC KEY-----\nMHcCAQEEIOSCfDNmx0qe6dncV4tg==\n-----END EC PUBLIC KEY-----\n" - token := "someToken" - templateData := getTemplateData(clusterName, pullSecret, releaseImageList, releaseImage, releaseImageMirror, publicContainerRegistries, "minimal-iso", infraEnvID, publicKey, gencrypto.AuthType, token, "", "", haveMirrorConfig, agentClusterInstall.Spec.ProvisionRequirements.ControlPlaneAgents, agentClusterInstall.Spec.ProvisionRequirements.WorkerAgents, osImage, proxy) + agentAuthToken := "agentAuthToken" + userAuthToken := "userAuthToken" + watcherAuthToken := "watcherAuthToken" + templateData := getTemplateData(clusterName, pullSecret, releaseImageList, releaseImage, releaseImageMirror, publicContainerRegistries, "minimal-iso", infraEnvID, publicKey, gencrypto.AuthType, agentAuthToken, userAuthToken, watcherAuthToken, "", "", haveMirrorConfig, agentClusterInstall.Spec.ProvisionRequirements.ControlPlaneAgents, agentClusterInstall.Spec.ProvisionRequirements.WorkerAgents, osImage, proxy) assert.Equal(t, clusterName, templateData.ClusterName) assert.Equal(t, "http", templateData.ServiceProtocol) assert.Equal(t, pullSecret, templateData.PullSecret) @@ -110,16 +112,19 @@ func TestIgnition_getTemplateData(t *testing.T) { assert.Equal(t, proxy, templateData.Proxy) assert.Equal(t, publicKey, templateData.PublicKeyPEM) assert.Equal(t, gencrypto.AuthType, templateData.AuthType) - assert.Equal(t, token, templateData.Token) + assert.Equal(t, agentAuthToken, templateData.AgentAuthToken) + assert.Equal(t, userAuthToken, templateData.UserAuthToken) + assert.Equal(t, watcherAuthToken, templateData.WatcherAuthToken) } func TestIgnition_getRendezvousHostEnv(t *testing.T) { nodeZeroIP := "2001:db8::dead:beef" - token := "someToken" - rendezvousHostEnv := getRendezvousHostEnv("http", nodeZeroIP, token, workflow.AgentWorkflowTypeInstall) + agentAuthtoken := "agentAuthtoken" + userAuthToken := "userAuthToken" + rendezvousHostEnv := getRendezvousHostEnv("http", nodeZeroIP, agentAuthtoken, userAuthToken, workflow.AgentWorkflowTypeInstall) assert.Equal(t, - "NODE_ZERO_IP="+nodeZeroIP+"\nSERVICE_BASE_URL=http://["+nodeZeroIP+"]:8090/\nIMAGE_SERVICE_BASE_URL=http://["+nodeZeroIP+"]:8888/\nAGENT_AUTH_TOKEN="+token+"\nPULL_SECRET_TOKEN="+token+"\nWORKFLOW_TYPE=install\n", + "NODE_ZERO_IP="+nodeZeroIP+"\nSERVICE_BASE_URL=http://["+nodeZeroIP+"]:8090/\nIMAGE_SERVICE_BASE_URL=http://["+nodeZeroIP+"]:8888/\nPULL_SECRET_TOKEN="+agentAuthtoken+"\nUSER_AUTH_TOKEN="+userAuthToken+"\nWORKFLOW_TYPE=install\n", rendezvousHostEnv) } From 58f798c8a6186fc6878cc28c52c0e193d4efff9f Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Wed, 23 Oct 2024 00:25:45 -0400 Subject: [PATCH 03/12] update keyname --- pkg/asset/agent/gencrypto/authconfig.go | 2 +- pkg/asset/agent/gencrypto/authconfig_test.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/asset/agent/gencrypto/authconfig.go b/pkg/asset/agent/gencrypto/authconfig.go index 384e85d0c7c..df616a9f2f3 100644 --- a/pkg/asset/agent/gencrypto/authconfig.go +++ b/pkg/asset/agent/gencrypto/authconfig.go @@ -181,7 +181,7 @@ func keyPairPEM() (string, string, error) { func generateToken(userPersona string, privateKeyPem string, expiry *time.Time) (string, error) { // Create the JWT claims claims := jwt.MapClaims{ - "sub": userPersona, + "auth_scheme": userPersona, } // Set the expiry time if provided if expiry != nil { diff --git a/pkg/asset/agent/gencrypto/authconfig_test.go b/pkg/asset/agent/gencrypto/authconfig_test.go index 298f7f5c0b2..6eadc407ea1 100644 --- a/pkg/asset/agent/gencrypto/authconfig_test.go +++ b/pkg/asset/agent/gencrypto/authconfig_test.go @@ -40,19 +40,19 @@ func TestAuthConfig_Generate(t *testing.T) { // verify each token is signed with correct persona claims, err := ParseToken(authConfigAsset.AgentAuthToken) assert.NoError(t, err) - persona, ok := claims["sub"].(string) + persona, ok := claims["auth_scheme"].(string) assert.Equal(t, persona, agentPersona) assert.Equal(t, ok, true) claims, err = ParseToken(authConfigAsset.UserAuthToken) assert.NoError(t, err) - persona, ok = claims["sub"].(string) + persona, ok = claims["auth_scheme"].(string) assert.Equal(t, persona, userPersona) assert.Equal(t, ok, true) claims, err = ParseToken(authConfigAsset.WatcherAuthToken) assert.NoError(t, err) - persona, ok = claims["sub"].(string) + persona, ok = claims["auth_scheme"].(string) assert.Equal(t, persona, watcherPersona) assert.Equal(t, ok, true) }) From dd4713b41783e32c5e9d99c49bab6e1f970bdbcd Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Wed, 6 Nov 2024 09:41:22 -0500 Subject: [PATCH 04/12] Add comments --- pkg/asset/agent/gencrypto/auth_utils.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/asset/agent/gencrypto/auth_utils.go b/pkg/asset/agent/gencrypto/auth_utils.go index 366c562c48b..2b0e6089cee 100644 --- a/pkg/asset/agent/gencrypto/auth_utils.go +++ b/pkg/asset/agent/gencrypto/auth_utils.go @@ -30,6 +30,8 @@ func ParseToken(tokenString string) (jwt.MapClaims, error) { } // ParseExpirationFromToken checks if the token is expired or not. +// Returns zero time on error for consistent return type; caller should ignore time on error. +// Otherwise returns the token expiry time. func ParseExpirationFromToken(tokenString string) (time.Time, error) { claims, err := ParseToken(tokenString) if err != nil { From 7a3528bf337dec1f1a269fea1496a053c4448470 Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Wed, 6 Nov 2024 09:51:44 -0500 Subject: [PATCH 05/12] Make PATCH request in sync with other requests ( used in appliance repo) --- data/data/agent/files/usr/local/bin/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/data/agent/files/usr/local/bin/common.sh b/data/data/agent/files/usr/local/bin/common.sh index 4b58aede80c..a37e27a9743 100644 --- a/data/data/agent/files/usr/local/bin/common.sh +++ b/data/data/agent/files/usr/local/bin/common.sh @@ -16,7 +16,7 @@ curl_assisted_service() { ;; "PATCH") curl -s -S -X PATCH "${additional_options[@]}" "${baseURL}${endpoint}" \ - -H "Authorization: ${AGENT_AUTH_TOKEN}" \ + -H "Authorization: ${authz}" \ -H "accept: application/json" \ -H "Content-Type: application/json" \ ;; From 60d37d07ee65f0144274073c4ba2315856374f79 Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Thu, 7 Nov 2024 10:11:27 -0500 Subject: [PATCH 06/12] Day2 monitor use case. Save watcherAuthToken in the secret --- data/data/agent/files/usr/local/bin/add-node.sh | 8 ++++---- pkg/asset/agent/gencrypto/authconfig.go | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/data/data/agent/files/usr/local/bin/add-node.sh b/data/data/agent/files/usr/local/bin/add-node.sh index 9ee2459386c..b8d6c5d1c18 100644 --- a/data/data/agent/files/usr/local/bin/add-node.sh +++ b/data/data/agent/files/usr/local/bin/add-node.sh @@ -10,7 +10,7 @@ cluster_id="" while [[ "${cluster_id}" = "" ]] do # Get cluster id - cluster_id=$(curl_assisted_service "/clusters" | jq -r .[].id) + cluster_id=$(curl_assisted_service "/clusters" GET "$USER_AUTH_TOKEN" | jq -r .[].id) if [[ "${cluster_id}" = "" ]]; then sleep 2 fi @@ -24,7 +24,7 @@ status_issue="90_add-node" host_ready=false while [[ $host_ready == false ]] do - host_status=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" | jq -r ".[].status") + host_status=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET "$USER_AUTH_TOKEN" | jq -r ".[].status") if [[ "${host_status}" != "known" ]]; then printf '\\e{yellow}Waiting for the host to be ready' | set_issue "${status_issue}" sleep 10 @@ -33,12 +33,12 @@ do fi done -HOST_ID=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" | jq -r '.[].id') +HOST_ID=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET "$USER_AUTH_TOKEN" | jq -r '.[].id') printf '\nHost %s is ready for installation\n' "${HOST_ID}" 1>&2 clear_issue "${status_issue}" # Add the current host to the cluster -res=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts/${HOST_ID}/actions/install" POST -w "%{http_code}" -o /dev/null) +res=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts/${HOST_ID}/actions/install" POST "$USER_AUTH_TOKEN" -w "%{http_code}" -o /dev/null) if [[ $res = "202" ]]; then printf '\nHost installation started\n' 1>&2 else diff --git a/pkg/asset/agent/gencrypto/authconfig.go b/pkg/asset/agent/gencrypto/authconfig.go index df616a9f2f3..b20a2a55a3f 100644 --- a/pkg/asset/agent/gencrypto/authconfig.go +++ b/pkg/asset/agent/gencrypto/authconfig.go @@ -29,7 +29,7 @@ import ( var ( authTokenSecretNamespace = "openshift-config" //nolint:gosec // no sensitive info authTokenSecretName = "agent-auth-token" //nolint:gosec // no sensitive info - authTokenSecretDataKey = "agentAuthToken" + authTokenSecretDataKey = "watcherAuthToken" authTokenPublicDataKey = "authTokenPublicKey" ) @@ -259,7 +259,7 @@ func (a *AuthConfig) createOrUpdateAuthTokenSecret(kubeconfigPath string) error } } else { // Update the token in asset store with the retrieved token from the cluster - a.AgentAuthToken = retrievedToken + a.WatcherAuthToken = retrievedToken // get the token expiry time of the retrieved token from the cluster a.AuthTokenExpiry = expiryTime.UTC().Format(time.RFC3339) @@ -287,7 +287,7 @@ func (a *AuthConfig) createSecret(k8sclientset kubernetes.Interface) error { }, Type: corev1.SecretTypeOpaque, Data: map[string][]byte{ - authTokenSecretDataKey: []byte(a.AgentAuthToken), + authTokenSecretDataKey: []byte(a.WatcherAuthToken), authTokenPublicDataKey: []byte(a.PublicKey), }, } @@ -302,7 +302,7 @@ func (a *AuthConfig) createSecret(k8sclientset kubernetes.Interface) error { } func (a *AuthConfig) refreshAuthTokenSecret(k8sclientset kubernetes.Interface, retrievedSecret *corev1.Secret) error { - retrievedSecret.Data[authTokenSecretDataKey] = []byte(a.AgentAuthToken) + retrievedSecret.Data[authTokenSecretDataKey] = []byte(a.WatcherAuthToken) retrievedSecret.Data[authTokenPublicDataKey] = []byte(a.PublicKey) // only for informational purposes retrievedSecret.Annotations["updatedAt"] = time.Now().UTC().Format(time.RFC3339) @@ -336,11 +336,11 @@ func GetAuthTokenFromCluster(ctx context.Context, kubeconfigPath string) (string } func extractAuthTokenFromSecret(secret *corev1.Secret) (string, error) { - existingAgentAuthToken, exists := secret.Data[authTokenSecretDataKey] - if !exists || len(existingAgentAuthToken) == 0 { + existingWatcherAuthToken, exists := secret.Data[authTokenSecretDataKey] + if !exists || len(existingWatcherAuthToken) == 0 { return "", fmt.Errorf("auth token secret %s/%s does not contain the key %s or is empty", authTokenSecretNamespace, authTokenSecretName, authTokenSecretDataKey) } - return string(existingAgentAuthToken), nil + return string(existingWatcherAuthToken), nil } func extractPublicKeyFromSecret(secret *corev1.Secret) (string, error) { From e2e19d28c5039d27bd78c1451428030a4af7a58a Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Thu, 7 Nov 2024 10:15:29 -0500 Subject: [PATCH 07/12] Rename var to a common name AUTH_TOKEN_EXPIRY. All the 3 tokens expire at the same time. --- cmd/node-joiner/testdata/add-nodes.txt | 2 +- data/data/agent/files/usr/local/bin/agent-auth-token-status.sh | 2 +- pkg/asset/agent/image/ignition.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/node-joiner/testdata/add-nodes.txt b/cmd/node-joiner/testdata/add-nodes.txt index 868cfd39690..767d26930ef 100644 --- a/cmd/node-joiner/testdata/add-nodes.txt +++ b/cmd/node-joiner/testdata/add-nodes.txt @@ -38,7 +38,7 @@ unqualified-search-registries = [] CLUSTER_ID=c37c9544-4320-4380-9d8b-0753a4d9ea57 CLUSTER_NAME=ostest CLUSTER_API_VIP_DNS_NAME=api.ostest.test.metalkube.org -AGENT_AUTH_TOKEN_EXPIRY=.* +AUTH_TOKEN_EXPIRY=.* -- expected/grub.cfg -- .*fips=1.* -- expected/import-cluster-config.json -- diff --git a/data/data/agent/files/usr/local/bin/agent-auth-token-status.sh b/data/data/agent/files/usr/local/bin/agent-auth-token-status.sh index 33549b13b5e..efffdd0f5d5 100644 --- a/data/data/agent/files/usr/local/bin/agent-auth-token-status.sh +++ b/data/data/agent/files/usr/local/bin/agent-auth-token-status.sh @@ -9,7 +9,7 @@ status_issue="65_token" export TZ=UTC check_token_expiry() { - expiry_epoch=$(date -d "${AGENT_AUTH_TOKEN_EXPIRY}" +%s) + expiry_epoch=$(date -d "${AUTH_TOKEN_EXPIRY}" +%s) current_epoch=$(date +%s) if [ "$current_epoch" -gt "$expiry_epoch" ]; then diff --git a/pkg/asset/agent/image/ignition.go b/pkg/asset/agent/image/ignition.go index 42f88e124fb..23437ffedcb 100644 --- a/pkg/asset/agent/image/ignition.go +++ b/pkg/asset/agent/image/ignition.go @@ -474,7 +474,7 @@ func getAddNodesEnv(clusterInfo joiner.ClusterInfo, authTokenExpiry string) stri return fmt.Sprintf(`CLUSTER_ID=%s CLUSTER_NAME=%s CLUSTER_API_VIP_DNS_NAME=%s -AGENT_AUTH_TOKEN_EXPIRY=%s +AUTH_TOKEN_EXPIRY=%s `, clusterInfo.ClusterID, clusterInfo.ClusterName, clusterInfo.APIDNSName, authTokenExpiry) } From e45f4d6453926f98e91792224b0fee1e497fde5e Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Tue, 12 Nov 2024 22:56:52 -0500 Subject: [PATCH 08/12] code refactoring --- pkg/asset/agent/gencrypto/authconfig.go | 54 ++++++++------------ pkg/asset/agent/gencrypto/authconfig_test.go | 2 + 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/pkg/asset/agent/gencrypto/authconfig.go b/pkg/asset/agent/gencrypto/authconfig.go index b20a2a55a3f..f1ba353508f 100644 --- a/pkg/asset/agent/gencrypto/authconfig.go +++ b/pkg/asset/agent/gencrypto/authconfig.go @@ -71,26 +71,26 @@ func (a *AuthConfig) Generate(_ context.Context, dependencies asset.Parents) err a.PublicKey = encodedPubKeyPEM + tokens := map[string]*string{ + agentPersona: &a.AgentAuthToken, + userPersona: &a.UserAuthToken, + watcherPersona: &a.WatcherAuthToken, + } + + generateAndAssignToken := func(persona, privateKey string, expiry *time.Time) (string, error) { + return generateToken(persona, privateKey, expiry) + } + switch agentWorkflow.Workflow { case workflow.AgentWorkflowTypeInstall: // Auth tokens do not expire - agentAuthToken, err := generateToken(agentPersona, privateKey, nil) - if err != nil { - return err - } - a.AgentAuthToken = agentAuthToken - - userAuthToken, err := generateToken(userPersona, privateKey, nil) - if err != nil { - return err - } - a.UserAuthToken = userAuthToken - - watcherAuthToken, err := generateToken(watcherPersona, privateKey, nil) - if err != nil { - return err + for persona, tokenField := range tokens { + token, err := generateAndAssignToken(persona, privateKey, nil) + if err != nil { + return err + } + *tokenField = token } - a.WatcherAuthToken = watcherAuthToken case workflow.AgentWorkflowTypeAddNodes: addNodesConfig := &joiner.AddNodesConfig{} @@ -100,23 +100,13 @@ func (a *AuthConfig) Generate(_ context.Context, dependencies asset.Parents) err expiry := time.Now().UTC().Add(48 * time.Hour) a.AuthTokenExpiry = expiry.Format(time.RFC3339) - agentAuthToken, err := generateToken(agentPersona, privateKey, &expiry) - if err != nil { - return err - } - a.AgentAuthToken = agentAuthToken - - userAuthToken, err := generateToken(userPersona, privateKey, &expiry) - if err != nil { - return err - } - a.UserAuthToken = userAuthToken - - watcherAuthToken, err := generateToken(watcherPersona, privateKey, &expiry) - if err != nil { - return err + for persona, tokenField := range tokens { + token, err := generateAndAssignToken(persona, privateKey, &expiry) + if err != nil { + return err + } + *tokenField = token } - a.WatcherAuthToken = watcherAuthToken err = a.createOrUpdateAuthTokenSecret(addNodesConfig.Params.Kubeconfig) if err != nil { diff --git a/pkg/asset/agent/gencrypto/authconfig_test.go b/pkg/asset/agent/gencrypto/authconfig_test.go index 6eadc407ea1..d29da3e653b 100644 --- a/pkg/asset/agent/gencrypto/authconfig_test.go +++ b/pkg/asset/agent/gencrypto/authconfig_test.go @@ -31,6 +31,8 @@ func TestAuthConfig_Generate(t *testing.T) { assert.NoError(t, err) assert.NotEmpty(t, authConfigAsset.PublicKey) assert.NotEmpty(t, authConfigAsset.AgentAuthToken) + assert.NotEmpty(t, authConfigAsset.UserAuthToken) + assert.NotEmpty(t, authConfigAsset.WatcherAuthToken) // All the 3 tokens should be unique assert.NotEqual(t, authConfigAsset.AgentAuthToken, authConfigAsset.UserAuthToken) From b346e46504d3b5fe3c2726d72804b29c00428db0 Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Wed, 13 Nov 2024 20:42:19 -0500 Subject: [PATCH 09/12] code optimization --- .../agent/files/usr/local/bin/add-node.sh | 8 ++--- data/data/agent/files/usr/local/bin/common.sh | 32 +++++++------------ .../agent/files/usr/local/bin/start-agent.sh | 2 +- .../local/bin/start-cluster-installation.sh | 8 ++--- .../local/bin/wait-for-assisted-service.sh | 2 +- .../assisted-service.env.template | 1 - 6 files changed, 21 insertions(+), 32 deletions(-) diff --git a/data/data/agent/files/usr/local/bin/add-node.sh b/data/data/agent/files/usr/local/bin/add-node.sh index b8d6c5d1c18..09ab698a6a2 100644 --- a/data/data/agent/files/usr/local/bin/add-node.sh +++ b/data/data/agent/files/usr/local/bin/add-node.sh @@ -10,7 +10,7 @@ cluster_id="" while [[ "${cluster_id}" = "" ]] do # Get cluster id - cluster_id=$(curl_assisted_service "/clusters" GET "$USER_AUTH_TOKEN" | jq -r .[].id) + cluster_id=$(curl_assisted_service "/clusters" GET | jq -r .[].id) if [[ "${cluster_id}" = "" ]]; then sleep 2 fi @@ -24,7 +24,7 @@ status_issue="90_add-node" host_ready=false while [[ $host_ready == false ]] do - host_status=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET "$USER_AUTH_TOKEN" | jq -r ".[].status") + host_status=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET | jq -r ".[].status") if [[ "${host_status}" != "known" ]]; then printf '\\e{yellow}Waiting for the host to be ready' | set_issue "${status_issue}" sleep 10 @@ -33,12 +33,12 @@ do fi done -HOST_ID=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET "$USER_AUTH_TOKEN" | jq -r '.[].id') +HOST_ID=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET | jq -r '.[].id') printf '\nHost %s is ready for installation\n' "${HOST_ID}" 1>&2 clear_issue "${status_issue}" # Add the current host to the cluster -res=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts/${HOST_ID}/actions/install" POST "$USER_AUTH_TOKEN" -w "%{http_code}" -o /dev/null) +res=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts/${HOST_ID}/actions/install" POST -w "%{http_code}" -o /dev/null) if [[ $res = "202" ]]; then printf '\nHost installation started\n' 1>&2 else diff --git a/data/data/agent/files/usr/local/bin/common.sh b/data/data/agent/files/usr/local/bin/common.sh index a37e27a9743..118eb77b249 100644 --- a/data/data/agent/files/usr/local/bin/common.sh +++ b/data/data/agent/files/usr/local/bin/common.sh @@ -3,27 +3,17 @@ curl_assisted_service() { local endpoint=$1 local method=${2:-GET} - local authz=${3:-} - local additional_options=("${@:4}") # Capture all arguments starting from the fourth one + local additional_options=("${@:3}") # Capture all arguments starting from the third one local baseURL="${SERVICE_BASE_URL}api/assisted-install/v2" - case "${method}" in - "POST") - curl -s -S -X POST "${additional_options[@]}" "${baseURL}${endpoint}" \ - -H "Authorization: ${authz}" \ - -H "accept: application/json" \ - -H "Content-Type: application/json" \ - ;; - "PATCH") - curl -s -S -X PATCH "${additional_options[@]}" "${baseURL}${endpoint}" \ - -H "Authorization: ${authz}" \ - -H "accept: application/json" \ - -H "Content-Type: application/json" \ - ;; - "GET") - curl -s -S -X GET "${additional_options[@]}" "${baseURL}${endpoint}" \ - -H "Authorization: ${authz}" \ - -H "Accept: application/json" - ;; - esac + headers=( + -s -S + -H "Authorization: ${USER_AUTH_TOKEN}" + -H "accept: application/json" + ) + + [[ "$method" == "POST" || "$method" == "PATCH" ]] && headers+=(-H "Content-Type: application/json") + + curl "${headers[@]}" -X "${method}" "${additional_options[@]}" "${baseURL}${endpoint}" + } diff --git a/data/data/agent/files/usr/local/bin/start-agent.sh b/data/data/agent/files/usr/local/bin/start-agent.sh index 92fdfbb03a0..62975c64883 100644 --- a/data/data/agent/files/usr/local/bin/start-agent.sh +++ b/data/data/agent/files/usr/local/bin/start-agent.sh @@ -8,7 +8,7 @@ INFRA_ENV_ID="" until [[ $INFRA_ENV_ID != "" && $INFRA_ENV_ID != "null" ]]; do sleep 5 >&2 echo "Querying assisted-service for infra-env-id..." - INFRA_ENV_ID=$(curl_assisted_service "/infra-envs" GET "$USER_AUTH_TOKEN" | jq -r '.[0].id') + INFRA_ENV_ID=$(curl_assisted_service "/infra-envs" GET | jq -r '.[0].id') done echo "Fetched infra-env-id and found: $INFRA_ENV_ID" diff --git a/data/data/agent/files/usr/local/bin/start-cluster-installation.sh b/data/data/agent/files/usr/local/bin/start-cluster-installation.sh index 48ad90be0e6..cc614c3cf14 100644 --- a/data/data/agent/files/usr/local/bin/start-cluster-installation.sh +++ b/data/data/agent/files/usr/local/bin/start-cluster-installation.sh @@ -10,7 +10,7 @@ cluster_id="" while [[ "${cluster_id}" = "" ]] do # Get cluster id - cluster_id=$(curl_assisted_service "/clusters" GET "$USER_AUTH_TOKEN" | jq -r .[].id) + cluster_id=$(curl_assisted_service "/clusters" GET | jq -r .[].id) if [[ "${cluster_id}" = "" ]]; then sleep 2 fi @@ -28,7 +28,7 @@ status_issue="90_start-install" num_known_hosts() { local known_hosts=0 local insufficient_hosts=0 - host_status=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET "$USER_AUTH_TOKEN" | jq -r .[].status) + host_status=$(curl_assisted_service "/infra-envs/${INFRA_ENV_ID}/hosts" GET | jq -r .[].status) if [[ -n ${host_status} ]]; then for status in ${host_status}; do if [[ "${status}" == "known" ]]; then @@ -58,7 +58,7 @@ clear_issue "${status_issue}" while [[ "${cluster_status}" != "installed" ]] do sleep 5 - cluster_info="$(curl_assisted_service "/clusters" GET "$USER_AUTH_TOKEN")" + cluster_info="$(curl_assisted_service "/clusters" GET)" cluster_status=$(printf '%s' "${cluster_info}" | jq -r .[].status) echo "Cluster status: ${cluster_status}" 1>&2 # Start the cluster install, if it transitions back to Ready due to a failure, @@ -66,7 +66,7 @@ do case "${cluster_status}" in "ready") echo "Starting cluster installation..." 1>&2 - res=$(curl_assisted_service "/clusters/${cluster_id}/actions/install" POST "$USER_AUTH_TOKEN" -w "%{http_code}" -o /dev/null) + res=$(curl_assisted_service "/clusters/${cluster_id}/actions/install" POST -w "%{http_code}" -o /dev/null) if [[ $res = "202" ]]; then printf '\nCluster installation started\n' 1>&2 fi diff --git a/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh b/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh index bf9d65ce675..d68b63835d7 100644 --- a/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh +++ b/data/data/agent/files/usr/local/bin/wait-for-assisted-service.sh @@ -6,7 +6,7 @@ source "common.sh" echo "Waiting for assisted-service to be ready" -until curl_assisted_service "/infra-envs" GET "$USER_AUTH_TOKEN" -o /dev/null --silent --fail; do +until curl_assisted_service "/infra-envs" GET -o /dev/null --silent --fail; do printf '.' sleep 5 done diff --git a/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template b/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template index 37be1de480a..2583c6832b5 100644 --- a/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template +++ b/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template @@ -20,6 +20,5 @@ OPENSHIFT_INSTALL_RELEASE_IMAGE_MIRROR={{.ReleaseImageMirror}} STORAGE=filesystem INFRA_ENV_ID={{.InfraEnvID}} EC_PUBLIC_KEY_PEM={{.PublicKeyPEM}} -AGENT_AUTH_TOKEN={{.AgentAuthToken}} USER_AUTH_TOKEN={{.UserAuthToken}} WATCHER_AUTH_TOKEN={{.WatcherAuthToken}} From f7aa52045264c51010f518c738e1e3f20955a84b Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Thu, 14 Nov 2024 11:20:49 -0500 Subject: [PATCH 10/12] Enable agent-installer-local auth type --- .../local/share/assisted-service/assisted-service.env.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template b/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template index 2583c6832b5..cdd6e7a5e3c 100644 --- a/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template +++ b/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template @@ -1,4 +1,4 @@ -AUTH_TYPE=none +AUTH_TYPE=={{.AuthType}} DB_HOST=127.0.0.1 DB_NAME=installer DB_PASS=admin From fcbc5af1ad2b7072674b4defa9d4a001f09349ad Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Thu, 14 Nov 2024 12:08:53 -0500 Subject: [PATCH 11/12] refactor --- pkg/asset/agent/gencrypto/authconfig.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg/asset/agent/gencrypto/authconfig.go b/pkg/asset/agent/gencrypto/authconfig.go index f1ba353508f..46ec9bbae99 100644 --- a/pkg/asset/agent/gencrypto/authconfig.go +++ b/pkg/asset/agent/gencrypto/authconfig.go @@ -77,15 +77,11 @@ func (a *AuthConfig) Generate(_ context.Context, dependencies asset.Parents) err watcherPersona: &a.WatcherAuthToken, } - generateAndAssignToken := func(persona, privateKey string, expiry *time.Time) (string, error) { - return generateToken(persona, privateKey, expiry) - } - switch agentWorkflow.Workflow { case workflow.AgentWorkflowTypeInstall: // Auth tokens do not expire for persona, tokenField := range tokens { - token, err := generateAndAssignToken(persona, privateKey, nil) + token, err := generateToken(persona, privateKey, nil) if err != nil { return err } @@ -101,7 +97,7 @@ func (a *AuthConfig) Generate(_ context.Context, dependencies asset.Parents) err a.AuthTokenExpiry = expiry.Format(time.RFC3339) for persona, tokenField := range tokens { - token, err := generateAndAssignToken(persona, privateKey, &expiry) + token, err := generateToken(persona, privateKey, &expiry) if err != nil { return err } From 4185056a98870c2bd3aff5139b3d86dd7a573dd5 Mon Sep 17 00:00:00 2001 From: Pawan Pinjarkar Date: Thu, 14 Nov 2024 18:31:14 -0500 Subject: [PATCH 12/12] typo --- .../local/share/assisted-service/assisted-service.env.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template b/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template index cdd6e7a5e3c..491f95c41c4 100644 --- a/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template +++ b/data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template @@ -1,4 +1,4 @@ -AUTH_TYPE=={{.AuthType}} +AUTH_TYPE={{.AuthType}} DB_HOST=127.0.0.1 DB_NAME=installer DB_PASS=admin