Skip to content

Commit 3075c32

Browse files
Merge pull request openshift#8717 from pawanpinjarkar/day2-auth
AGENT-919: Authenticate day2 operations
2 parents c4c45d0 + c5048c1 commit 3075c32

File tree

10 files changed

+321
-29
lines changed

10 files changed

+321
-29
lines changed

data/data/agent/files/usr/local/share/assisted-service/assisted-service.env.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ OPENSHIFT_INSTALL_RELEASE_IMAGE_MIRROR={{.ReleaseImageMirror}}
1919
STORAGE=filesystem
2020
INFRA_ENV_ID={{.InfraEnvID}}
2121
EC_PUBLIC_KEY_PEM={{.PublicKeyPEM}}
22-
AGENT_AUTH_TOKEN={{.Token}}
22+
AGENT_AUTH_TOKEN={{.Token}}

data/data/agent/systemd/units/agent-import-cluster.service.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ EnvironmentFile=/usr/local/share/assisted-service/assisted-service.env
1616
EnvironmentFile=/etc/assisted/add-nodes.env
1717
ExecStartPre=/bin/rm -f %t/%n.ctr-id
1818
ExecStartPre=/usr/local/bin/wait-for-assisted-service.sh
19-
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 $SERVICE_IMAGE /usr/local/bin/agent-installer-client importCluster
19+
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
2020
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
2121
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
2222

pkg/agent/cluster.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/openshift/assisted-service/client/installer"
1717
"github.com/openshift/assisted-service/models"
18+
"github.com/openshift/installer/pkg/asset/agent/gencrypto"
1819
"github.com/openshift/installer/pkg/asset/agent/workflow"
1920
"github.com/openshift/installer/pkg/gather/ssh"
2021
)
@@ -70,9 +71,22 @@ func NewCluster(ctx context.Context, assetDir, rendezvousIP, kubeconfigPath, ssh
7071
czero := &Cluster{}
7172
capi := &clientSet{}
7273

73-
authToken, err := FindAuthTokenFromAssetStore(assetDir)
74-
if err != nil {
75-
logrus.Fatal(err)
74+
var authToken string
75+
var err error
76+
77+
switch workflowType {
78+
case workflow.AgentWorkflowTypeInstall:
79+
authToken, err = FindAuthTokenFromAssetStore(assetDir)
80+
if err != nil {
81+
return nil, err
82+
}
83+
case workflow.AgentWorkflowTypeAddNodes:
84+
authToken, err = gencrypto.GetAuthTokenFromCluster(ctx, kubeconfigPath)
85+
if err != nil {
86+
return nil, err
87+
}
88+
default:
89+
return nil, fmt.Errorf("AgentWorkflowType value not supported: %s", workflowType)
7690
}
7791

7892
restclient := NewNodeZeroRestClient(ctx, rendezvousIP, sshKey, authToken)

pkg/agent/rest.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func FindRendezvouIPAndSSHKeyFromAssetStore(assetDir string) (string, string, er
119119
return rendezvousIP, sshKey, nil
120120
}
121121

122-
// FindAuthTokenFromAssetStore returns the auth token.
122+
// FindAuthTokenFromAssetStore returns the auth token from asset store.
123123
func FindAuthTokenFromAssetStore(assetDir string) (string, error) {
124124
authConfigAsset := &gencrypto.AuthConfig{}
125125

@@ -135,9 +135,12 @@ func FindAuthTokenFromAssetStore(assetDir string) (string, error) {
135135
return "", errors.New("failed to load AuthConfig")
136136
}
137137

138-
token := authConfig.(*gencrypto.AuthConfig).Token
138+
var authToken string
139+
if authConfig != nil {
140+
authToken = authConfig.(*gencrypto.AuthConfig).AgentAuthToken
141+
}
139142

140-
return token, nil
143+
return authToken, nil
141144
}
142145

143146
// IsRestAPILive Determine if the Agent Rest API on node zero has initialized

pkg/asset/agent/gencrypto/auth_utils.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package gencrypto
22

33
import (
4+
"time"
5+
46
"github.com/go-openapi/runtime"
57
"github.com/go-openapi/strfmt"
8+
"github.com/golang-jwt/jwt/v4"
9+
"github.com/pkg/errors"
610
)
711

812
// UserAuthHeaderWriter sets the JWT authorization token.
@@ -11,3 +15,24 @@ func UserAuthHeaderWriter(token string) runtime.ClientAuthInfoWriter {
1115
return r.SetHeaderParam("Authorization", token)
1216
})
1317
}
18+
19+
// ParseExpirationFromToken checks if the token is expired or not.
20+
func ParseExpirationFromToken(tokenString string) (time.Time, error) {
21+
token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{})
22+
if err != nil {
23+
return time.Time{}, err
24+
}
25+
claims, ok := token.Claims.(jwt.MapClaims)
26+
if !ok {
27+
return time.Time{}, errors.Errorf("malformed token claims in url")
28+
}
29+
exp, ok := claims["exp"].(float64)
30+
if !ok {
31+
return time.Time{}, errors.Errorf("token missing 'exp' claim")
32+
}
33+
expTime := time.Unix(int64(exp), 0)
34+
expiresAt := strfmt.DateTime(expTime)
35+
expiryTime := time.Time(expiresAt)
36+
37+
return expiryTime, nil
38+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package gencrypto
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/google/uuid"
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestParseExpirationFromToken(t *testing.T) {
12+
publicKey, privateKey, err := keyPairPEM()
13+
assert.NotEmpty(t, publicKey)
14+
assert.NotEmpty(t, privateKey)
15+
assert.NoError(t, err)
16+
17+
infraEnvID := uuid.New().String()
18+
19+
tokenNoExp, err := generateToken(infraEnvID, privateKey)
20+
assert.NotEmpty(t, tokenNoExp)
21+
assert.NoError(t, err)
22+
23+
expiry := time.Now().UTC().Add(30 * time.Second)
24+
tokenWithExp, err := generateToken(infraEnvID, privateKey, expiry)
25+
assert.NotEmpty(t, tokenWithExp)
26+
assert.NoError(t, err)
27+
28+
cases := []struct {
29+
name, token, errorMessage string
30+
expectedErr bool
31+
}{
32+
{
33+
name: "exp-claim-not-set",
34+
token: tokenNoExp,
35+
expectedErr: true,
36+
errorMessage: "token missing 'exp' claim",
37+
},
38+
{
39+
name: "exp-claim-set",
40+
token: tokenWithExp,
41+
},
42+
}
43+
for _, tc := range cases {
44+
t.Run(tc.name, func(t *testing.T) {
45+
_, err = ParseExpirationFromToken(tc.token)
46+
if tc.expectedErr {
47+
assert.EqualError(t, err, tc.errorMessage)
48+
} else {
49+
assert.NoError(t, err)
50+
}
51+
})
52+
}
53+
}

0 commit comments

Comments
 (0)