-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to create tokens #498
Conversation
@@ -428,7 +429,7 @@ type RepositoryList struct { | |||
// AppProjectList is list of AppProject resources | |||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | |||
type AppProjectList struct { | |||
metav1.TypeMeta `json:",inline"` | |||
metav1.TypeMeta `json:",inline""` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This extra quote is going to cause problems
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
@@ -453,6 +463,36 @@ type AppProjectSpec struct { | |||
|
|||
// Description contains optional project description | |||
Description string `json:"description,omitempty" protobuf:"bytes,3,opt,name=description"` | |||
|
|||
Roles []ProjectRole `protobuf:"bytes,4,rep,name=roles"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs the json annotation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
} | ||
|
||
// GetRoleIndex looks up the index of a role in a project by the name | ||
func (proj *AppProject) GetRoleIndex(name string) (int, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GetRoleIndex is not very useful as an exported method on project. It's really just implementation detail. Can we make this a unexported function inside the project app server instead? Or at least someplace other than types.go, which we should try to business logic to a minimum (unless we really feel every user of the type will need it).
I might feel better about it, it it were more useful like GetRoleByName().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved GetRoleByName to a separate file in the utils folder to get it out of the types.go.
util/rbac/rbac.go
Outdated
@@ -19,6 +20,7 @@ import ( | |||
"k8s.io/client-go/kubernetes" | |||
"k8s.io/client-go/tools/cache" | |||
|
|||
appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fact that we have to import an appclientset in the RBAC utility library, means we're not organizing the code very well. We should remove this import somehow, since this library is expected to be generic, and we have one internal project that depends on this RBAC library. In fact we eventually want to move the entire rbac library under argoproj/pkg instead of argoproj/argo-cd since we may need RBAC in other projects.
util/rbac/rbac.go
Outdated
@@ -122,10 +131,47 @@ func (e *Enforcer) defaultEnforceClaims(rvals ...interface{}) bool { | |||
} | |||
} | |||
user := jwtutil.GetField(mapClaims, "sub") | |||
if strings.HasPrefix(user, "proj:") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To fix the import issue, our custom defaultEnforceClaims
can be moved to an ArgoCD specific function, which can be supplied when instantiating the enforcer using NewEnforcer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the enforcer so that if a claims enforcer function isn't provided, then we will always return false
cmd/argocd/commands/project.go
Outdated
tokenCommand.AddCommand(NewProjectDeleteTokenCommand(clientOpts)) | ||
tokenCommand.AddCommand(NewProjectAddTokenPolicyCommand(clientOpts)) | ||
tokenCommand.AddCommand(NewProjectRemoveTokenPolicyCommand(clientOpts)) | ||
command.AddCommand(tokenCommand) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per our previous discussion, what users will be managing, are roles in project. And tokens will be one mechanism to authenticate to a role. IAM whitelist will be an eventual second. We need to rework the terminology on the CLI to reflect this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the cli command from token to role to address this issue.
// ProjectRoleMetatdata represents all the different types of roles a project can have | ||
// ProjectRoleMetatdata only one of its members may be specified for a specific role | ||
type ProjectRoleMetatdata struct { | ||
JwtToken *JwtTokenMetadata `protobuf:"bytes,1,opt,name=jwtToken"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move JWTToken directly under ProjectRole and get rid of ProjectRoleMetatdata. After thinking about it some more, the one of
property between JWT and IAM is not really necessary. We can support the mode where the same project role can be accessed by both an IAM role as well as JWT token.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, but I'm going to refactor it to allow a list of tokens as per our previous discussions
util/session/sessionmanager.go
Outdated
@@ -43,6 +43,12 @@ const ( | |||
badUserError = "Bad local superuser username" | |||
) | |||
|
|||
// JwtToken the metadata of a token | |||
type JwtToken struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This datastructure is redundant. The string returned by SessionManager.Create() is already a JWT token with information about when it was issued.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
util/session/sessionmanager.go
Outdated
if err != nil { | ||
return nil, err | ||
} | ||
return &JwtToken{Token: token, IssuedAt: now.Unix()}, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See previous comment. IssuedAt is already being generated in the claims so we don't need a wrapper around the token string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
79e4b07
to
9e317f8
Compare
cmd/argocd/commands/project.go
Outdated
roleCommand.AddCommand(NewProjectRoleDeleteTokenCommand(clientOpts)) | ||
roleCommand.AddCommand(NewProjectRoleAddPolicyCommand(clientOpts)) | ||
roleCommand.AddCommand(NewProjectRoleRemovePolicyCommand(clientOpts)) | ||
command.AddCommand(roleCommand) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of these roleCommand.AddCommand
should be happening in the NewProjectRoleCommand() function. So then the only thing that happens here is:
command.AddCommand(NewProjectRoleCommand(clientOpts))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 fixed
@@ -351,7 +370,7 @@ message SyncOperation { | |||
// Prune deletes resources that are no longer tracked in git | |||
optional bool prune = 2; | |||
|
|||
// DryRun will perform a `kubectl apply --dry-run` without actually performing the sync | |||
// DryRun will perform a `kubectl apply --dry-rudn` without actually performing the sync |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@@ -443,6 +443,15 @@ type AppProject struct { | |||
Spec AppProjectSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"` | |||
} | |||
|
|||
//ProjectPoliciesString returns Casabin formated string of a project's polcies for each role |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Casabin* typo. Also space after //
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
Name string `json:"name" protobuf:"bytes,1,opt,name=name"` | ||
// Policies Stores a list of casbin formated strings that define access policies for the role in the project. | ||
Policies []string `json:"policies" protobuf:"bytes,2,rep,name=policies"` | ||
JWTTokens []JWTToken `json:"JWTTokens" protobuf:"bytes,3,rep,name=JWTTokens"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The golang field name should be JWTTokens. But the JSON/proto field name should be lowercase jwtTokens
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
Gopkg.lock
Outdated
name = "github.com/GeertJohan/go.rice" | ||
packages = [ | ||
".", | ||
"embedded", | ||
"embedded" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you running older version of dep? I think you need to upgrade to dep 0.5 because otherwise we will flap between dep formats.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I was on 4.1. Let me know if the new changes from the dep ensure are a problem
cmd/argocd/commands/project.go
Outdated
fmt.Print(token.Token) | ||
}, | ||
} | ||
command.Flags().StringVarP(&timeBeforeExpiry, "timeBeforeExpiry", "s", "0s", "Time before the token will expire. (Default: No expiration)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets rename to expires-in
per my other comment. Also "Duration" will be a better description than time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, we shouldn't use camelCase for CLI flags, preferring dashes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
cmd/argocd/commands/project.go
Outdated
timeBeforeExpiry string | ||
) | ||
var command = &cobra.Command{ | ||
Use: "create-token PROJECT TOKEN-NAME [--seconds seconds]", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--seconds is inconsistent with the actual flag name, which I'm proposing to change to --expires-in
to match the API field name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
cmd/argocd/commands/project.go
Outdated
// NewProjectRoleDeleteTokenCommand returns a new instance of an `argocd proj role delete-token` command | ||
func NewProjectRoleDeleteTokenCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { | ||
var command = &cobra.Command{ | ||
Use: "delete-token PROJECT ROLE-NAME ISSUED_AT", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistency between dashes and underscore with ROLE-NAME ISSUED_AT
. Lets choose dashes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
cmd/argocd/commands/project.go
Outdated
fmt.Fprintf(w, "%s\n", role.Name) | ||
if role.JWTTokens != nil { | ||
for _, token := range role.JWTTokens { | ||
fmt.Fprintf(w, "%s\t%d\t%d\n", role.Name, token.IssuedAt, token.ExpiresAt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a token does not expire, I think this is going to print epoch zero (1970). Instead we should print <none>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I see that it will print 0
since this is '%d'. Instead can we print the issued at and expiration time in a human readable format. e.g. 2018-08-15T12:13:14?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed this issue by breaking the list role command into a list role and a get role command. The list role command would list all the roles and their descriptions. The get role command would list the name, description, policies, and JWT tokens of a role in a project. With the JWT token, the cli lists the issue-at value as a ID to used in the delete-token and two human readable tokens for issued-at and expires-at.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example output:
./dist/argocd proj role list guestbook
ROLE-NAME Description
test desc
asdfghjklasdfghjklasdfghjkl desc1
./dist/argocd proj role get guestbook test
Role Name: test
Description:desc
Policies:
p, proj:guestbook:test, applications, get, guestbook/guestbook-test, allow
p, proj:guestbook:test, applications, get, guestbook/*, allow
Jwt Tokens:
ID ISSUED-AT EXPIRES-AT
1534270415 Tue Aug 14 11:13:35 -0700 (4 hours ago) <none>
1534286505 2018-08-14T15:41:45-07:00 (16 minutes ago) 2018-08-24T15:41:45-07:00 (1 week from now)
1534286515 2018-08-14T15:41:55-07:00 (16 minutes ago) 2018-09-03T15:41:55-07:00 (2 weeks from now)
1534286520 2018-08-14T15:42:00-07:00 (16 minutes ago) 2018-09-04T15:42:00-07:00 (2 weeks from now)
1534286527 2018-08-14T15:42:07-07:00 (16 minutes ago) 2018-09-05T15:42:07-07:00 (3 weeks from now)
1534286539 2018-08-14T15:42:19-07:00 (15 minutes ago) 2018-10-13T15:42:19-07:00 (1 month from now)
1534286552 2018-08-14T15:42:32-07:00 (15 minutes ago) 2018-08-14T15:43:02-07:00 (15 minutes ago)
1534286554 2018-08-14T15:42:34-07:00 (15 minutes ago) 2018-08-14T15:43:04-07:00 (15 minutes ago)
1534286558 2018-08-14T15:42:38-07:00 (15 minutes ago) 2018-08-14T15:43:08-07:00 (15 minutes ago)```
@@ -283,6 +292,16 @@ message OperationState { | |||
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time finishedAt = 7; | |||
} | |||
|
|||
// ProjectRole represents a role that has access to a project | |||
message ProjectRole { | |||
optional string name = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I requested this earlier, but roles will need a description so that humans know the purpose of a role.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
7a582b0
to
f3b04fb
Compare
f3b04fb
to
49a6c27
Compare
49a6c27
to
b2218a4
Compare
9e3cae3
to
b90118e
Compare
05022c2
to
1a9d159
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Please squash and shorten the git commit message so it's not just a huge list of bullet points, before pushing.
Implemented Project Tokens (#472) using #228 as the overall design. In order to make it easier to add IAM authorization in the future, I created a more generic project role struct instead just creating a project token stuct. This will allow us to extend the project role to include IAMs specific roles without having to refactor the similar Jwt token work.