Skip to content

Commit 6c9643e

Browse files
committed
Credentials token and whoami handlers
1 parent 17766dc commit 6c9643e

8 files changed

+818
-0
lines changed

handler/config/credentials_token.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
Copyright © 2020 Portworx
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package configcli
17+
18+
import (
19+
"github.com/portworx/pxc/pkg/commander"
20+
"github.com/portworx/pxc/pkg/util"
21+
"github.com/spf13/cobra"
22+
)
23+
24+
// tokenCmd represents the token command
25+
var tokenCmd *cobra.Command
26+
27+
var _ = commander.RegisterCommandVar(func() {
28+
tokenCmd = &cobra.Command{
29+
Use: "token",
30+
Short: "Portworx token management commands",
31+
Run: func(cmd *cobra.Command, args []string) {
32+
util.Printf("Please see pxc config credentials token --help for more commands\n")
33+
},
34+
}
35+
})
36+
37+
var _ = commander.RegisterCommandInit(func() {
38+
CredentialsAddCommand(tokenCmd)
39+
})
40+
41+
func CredentialsTokenAddCommand(cmd *cobra.Command) {
42+
tokenCmd.AddCommand(cmd)
43+
}

handler/config/credentials_whoami.go

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
Copyright © 2020 Portworx
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package configcli
17+
18+
import (
19+
"fmt"
20+
"strings"
21+
"time"
22+
23+
"github.com/portworx/pxc/pkg/auth"
24+
"github.com/portworx/pxc/pkg/commander"
25+
"github.com/portworx/pxc/pkg/config"
26+
"github.com/portworx/pxc/pkg/portworx"
27+
"github.com/portworx/pxc/pkg/util"
28+
"github.com/spf13/cobra"
29+
)
30+
31+
type whoamiOptions struct {
32+
token string
33+
}
34+
35+
var (
36+
whoamiArgs *whoamiOptions
37+
whoamiCmd *cobra.Command
38+
)
39+
40+
var _ = commander.RegisterCommandVar(func() {
41+
whoamiArgs = &whoamiOptions{}
42+
whoamiCmd = &cobra.Command{
43+
Use: "whoami",
44+
Short: "Shows current authentication information",
45+
RunE: whoAmIExec,
46+
}
47+
})
48+
49+
var _ = commander.RegisterCommandInit(func() {
50+
CredentialsAddCommand(whoamiCmd)
51+
whoamiCmd.Flags().StringVar(&whoamiArgs.token,
52+
"auth-token", "", "Use this token instead of the token saved in the configuration. Useful for debugging tokens")
53+
})
54+
55+
func WhoAmIAddCommand(cmd *cobra.Command) {
56+
whoamiCmd.AddCommand(cmd)
57+
}
58+
59+
func whoAmIExec(cmd *cobra.Command, args []string) error {
60+
token := whoamiArgs.token
61+
if len(token) == 0 {
62+
authInfo := config.CM().GetCurrentAuthInfo()
63+
token = authInfo.Token
64+
65+
if len(authInfo.KubernetesAuthInfo.SecretName) != 0 &&
66+
len(authInfo.KubernetesAuthInfo.SecretNamespace) != 0 {
67+
var err error
68+
token, err = portworx.PxGetTokenFromSecret(authInfo.KubernetesAuthInfo.SecretName, authInfo.KubernetesAuthInfo.SecretNamespace)
69+
if err != nil {
70+
return fmt.Errorf("Unable to retreive token from Kubernetes: %v", err)
71+
}
72+
}
73+
if len(token) == 0 {
74+
util.Printf("No authentication information provided")
75+
return nil
76+
}
77+
}
78+
79+
expTime, err := auth.GetExpiration(token)
80+
if err != nil {
81+
return fmt.Errorf("Unable to get expiration information from token: %v", err)
82+
}
83+
iatTime, err := auth.GetIssuedAtTime(token)
84+
if err != nil {
85+
return fmt.Errorf("Unable to get issued time information from token: %v", err)
86+
}
87+
claims, err := auth.TokenClaims(token)
88+
if err != nil {
89+
return err
90+
}
91+
92+
status := "Ok"
93+
err = auth.ValidateToken(token)
94+
if err != nil {
95+
status = fmt.Sprintf("%v", err)
96+
}
97+
98+
util.Printf("Name: %s\n"+
99+
"Email: %s\n"+
100+
"Subject: %s\n"+
101+
"Groups: %s\n"+
102+
"Roles: %s\n"+
103+
"Issued At Time: %s\n"+
104+
"Expiration Time: %s\n"+
105+
"\n"+
106+
"Status: %s\n",
107+
claims.Name,
108+
claims.Email,
109+
claims.Subject,
110+
strings.Join(claims.Groups, ","),
111+
strings.Join(claims.Roles, ","),
112+
iatTime.Format(time.UnixDate),
113+
expTime.Format(time.UnixDate),
114+
status)
115+
116+
return nil
117+
118+
}

handler/config/token_generate.go

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
Copyright © 2020 Portworx
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package configcli
17+
18+
import (
19+
"fmt"
20+
"strings"
21+
"time"
22+
23+
"github.com/portworx/pxc/pkg/auth"
24+
"github.com/portworx/pxc/pkg/commander"
25+
"github.com/portworx/pxc/pkg/util"
26+
"github.com/sirupsen/logrus"
27+
"github.com/spf13/cobra"
28+
)
29+
30+
type tokenInfo struct {
31+
issuer string
32+
subject string
33+
name string
34+
email string
35+
roles string
36+
groups string
37+
}
38+
39+
type tokenGenOptions struct {
40+
sharedSecret string
41+
rsaPem string
42+
ecdsaPem string
43+
duration string
44+
output string
45+
token tokenInfo
46+
}
47+
48+
// tokenGenCmd represents the tokenGen command
49+
var (
50+
tokenGenArgs *tokenGenOptions
51+
tokenGenCmd *cobra.Command
52+
)
53+
54+
var _ = commander.RegisterCommandVar(func() {
55+
tokenGenArgs = &tokenGenOptions{}
56+
tokenGenCmd = &cobra.Command{
57+
Use: "generate",
58+
Aliases: []string{"gen"},
59+
Short: "Generate a Portworx token",
60+
RunE: tokenGenExec,
61+
}
62+
})
63+
64+
var _ = commander.RegisterCommandInit(func() {
65+
CredentialsTokenAddCommand(tokenGenCmd)
66+
tokenGenCmd.Flags().StringVar(&tokenGenArgs.sharedSecret,
67+
"shared-secret", "", "Shared secret to sign token")
68+
tokenGenCmd.Flags().StringVar(&tokenGenArgs.rsaPem,
69+
"rsa-private-keyfile", "", "RSA Private file to sign token")
70+
tokenGenCmd.Flags().StringVar(&tokenGenArgs.ecdsaPem,
71+
"ecdsa-private-keyfile", "", "ECDSA Private file to sign token")
72+
tokenGenCmd.Flags().StringVar(&tokenGenArgs.duration,
73+
"token-duration", "1d", "Duration of time where the token will be valid. "+
74+
"Postfix the duration by using "+
75+
auth.SecondDef+" for seconds, "+
76+
auth.MinuteDef+" for minutes, "+
77+
auth.HourDef+" for hours, "+
78+
auth.DayDef+" for days, and "+
79+
auth.YearDef+" for years.")
80+
tokenGenCmd.Flags().StringVar(&tokenGenArgs.token.issuer,
81+
"token-issuer", "portworx.com",
82+
"Issuer name of token. Do not use https:// in the issuer since it could indicate "+
83+
"that this is an OpenID Connect issuer.")
84+
tokenGenCmd.Flags().StringVar(&tokenGenArgs.token.name,
85+
"token-name", "", "Account name")
86+
tokenGenCmd.Flags().StringVar(&tokenGenArgs.token.subject,
87+
"token-subject", "", "Unique ID of this account")
88+
tokenGenCmd.Flags().StringVar(&tokenGenArgs.token.email,
89+
"token-email", "", "Unique ID of this account")
90+
tokenGenCmd.Flags().StringVar(&tokenGenArgs.token.roles,
91+
"token-roles", "", "Comma separated list of roles applied to this token")
92+
tokenGenCmd.Flags().StringVar(&tokenGenArgs.token.groups,
93+
"token-groups", "", "Comma separated list of groups which the token will be part of")
94+
95+
})
96+
97+
func TokenGenerateAddCommand(cmd *cobra.Command) {
98+
tokenGenCmd.AddCommand(cmd)
99+
}
100+
101+
func tokenGenExec(cmd *cobra.Command, args []string) error {
102+
103+
if len(tokenGenArgs.token.name) == 0 {
104+
return fmt.Errorf("Must supply an account name")
105+
} else if len(tokenGenArgs.token.email) == 0 {
106+
return fmt.Errorf("Must supply an email address")
107+
} else if len(tokenGenArgs.token.subject) == 0 {
108+
return fmt.Errorf("Must supply a unique identifier as the subject")
109+
}
110+
if len(tokenGenArgs.token.roles) == 0 {
111+
logrus.Warningf("Warning: No role provided")
112+
}
113+
if len(tokenGenArgs.token.groups) == 0 {
114+
logrus.Warningf("Warning: No role provided")
115+
}
116+
117+
claims := &auth.Claims{
118+
Name: tokenGenArgs.token.name,
119+
Email: tokenGenArgs.token.email,
120+
Subject: tokenGenArgs.token.subject,
121+
Roles: strings.Split(tokenGenArgs.token.roles, ","),
122+
Groups: strings.Split(tokenGenArgs.token.groups, ","),
123+
}
124+
125+
// Get duration
126+
options := &auth.Options{
127+
Issuer: tokenGenArgs.token.issuer,
128+
}
129+
expDuration, err := auth.ParseToDuration(tokenGenArgs.duration)
130+
if err != nil {
131+
return fmt.Errorf("Unable to parse duration")
132+
}
133+
options.Expiration = time.Now().Add(expDuration).Unix()
134+
135+
// Get signature
136+
var signature *auth.Signature
137+
if len(tokenGenArgs.sharedSecret) != 0 {
138+
signature, err = auth.NewSignatureSharedSecret(tokenGenArgs.sharedSecret)
139+
} else if len(tokenGenArgs.rsaPem) != 0 {
140+
signature, err = auth.NewSignatureRSAFromFile(tokenGenArgs.rsaPem)
141+
} else if len(tokenGenArgs.ecdsaPem) != 0 {
142+
signature, err = auth.NewSignatureECDSAFromFile(tokenGenArgs.ecdsaPem)
143+
} else {
144+
return fmt.Errorf("Must provide a secret key to sign token")
145+
}
146+
if err != nil {
147+
return fmt.Errorf("Unable to generate signature: %v", err)
148+
}
149+
150+
// Generate token
151+
token, err := auth.Token(claims, signature, options)
152+
if err != nil {
153+
return fmt.Errorf("Failed to create token: %v", err)
154+
}
155+
156+
// Print token
157+
util.Printf("%s\n", token)
158+
159+
return nil
160+
}

0 commit comments

Comments
 (0)