Skip to content

Adding support for server to authenticate agent#51

Merged
k8s-ci-robot merged 1 commit intokubernetes-sigs:masterfrom
dberkov:token
Feb 6, 2020
Merged

Adding support for server to authenticate agent#51
k8s-ci-robot merged 1 commit intokubernetes-sigs:masterfrom
dberkov:token

Conversation

@dberkov
Copy link
Copy Markdown
Contributor

@dberkov dberkov commented Jan 22, 2020

The PR allows to proxy-server authenticate proxy-agent.

Agent:

Agent sends in GRPC metadata token associated to the pod by kubernetes system.

Server

Server as part of the connection opening step, reads the token sent by agent, invokes kubernetes.TokenReviews API, checks the token is valid and belongs to agent's pod by validating namespace + service account of the token's owner .

General

All examples/kubernetes/* templates and READ.me procedure has been updated for supporting fully working e2e test of this feature in kubernetes.

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jan 22, 2020
@dberkov dberkov force-pushed the token branch 3 times, most recently from 26cf0c1 to 5762da5 Compare January 22, 2020 07:05
@dberkov
Copy link
Copy Markdown
Contributor Author

dberkov commented Jan 22, 2020

/test pull-apiserver-network-proxy-test

@dberkov
Copy link
Copy Markdown
Contributor Author

dberkov commented Jan 22, 2020

/assign @caesarxuchao @Jefftree

return fmt.Errorf("proxy server port %d must be greater than 0", o.proxyServerPort)
}
if o.saToken != "" {
if _, err := os.Stat(o.saToken); os.IsNotExist(err) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't ignore other types of error.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do exactly same validation for all other files (agentCert, agentKey, etc..). I would prefer to keep it as is and we can refactor entire project's validation methods in separate PR

}

if !r.Status.Authenticated {
return fmt.Errorf("lookup failed: service account jwt not valid")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a jwt?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep sa are jwt

CLUSTER_KEY=/etc/srv/kubernetes/pki/apiserver.key
```

# Register SERVER_TOKEN in [static-token-file](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#static-token-file)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "static-token" the standard way to authenticate a process running in the master node?

I think we can run the proxy server as a static pod, and then use a service account to authenticate it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown

@caesarxuchao caesarxuchao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more nits.

@Jefftree @dberkov have you manually tested it in GCE/GKE?

@dberkov I understand that it's difficult to write a complete test because we don't have the test framework that runs a k8s cluster. Can you add an integration test to tests/ to verify that the proxy-server denies the Connect request if the agent doesn't send a bearer token at all? That doesn't require a k8s cluster running.

@Jefftree
Copy link
Copy Markdown
Member

@dberkov @caesarxuchao: Since network proxy promises MTLS, can we enforce that either a cert or token must be sent by the proxy agent? If no token is sent, the konnectivity-server will reject the request and unregister the connection, but the konnectivity-agent pod will be in a infinite crash loop state, and keep trying to connect to the server with no token info supplied.

@dberkov
Copy link
Copy Markdown
Contributor Author

dberkov commented Jan 24, 2020

A few more nits.

@Jefftree @dberkov have you manually tested it in GCE/GKE?

@dberkov I understand that it's difficult to write a complete test because we don't have the test framework that runs a k8s cluster. Can you add an integration test to tests/ to verify that the proxy-server denies the Connect request if the agent doesn't send a bearer token at all? That doesn't require a k8s cluster running.

I have created pkg/agent/agentserver/server_test.go with full test coverage on new behavior on server side

Copy link
Copy Markdown
Member

@Jefftree Jefftree left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the tests! I've verified this on GKE and seems to be working fine per the instructions. One minor nit, but otherwise lgtm from me.

Will defer to Chao and Walter for approval.

/assign @cheftako

@dberkov
Copy link
Copy Markdown
Contributor Author

dberkov commented Jan 27, 2020

/test pull-apiserver-network-proxy-test

2 similar comments
@dberkov
Copy link
Copy Markdown
Contributor Author

dberkov commented Jan 27, 2020

/test pull-apiserver-network-proxy-test

@dberkov
Copy link
Copy Markdown
Contributor Author

dberkov commented Jan 27, 2020

/test pull-apiserver-network-proxy-test

}

if o.agentCert == "" && o.agentKey == "" && o.serviceAccountTokenPath == "" {
return fmt.Errorf("agent must enable certificate based or token based authentication")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this should be enforced from the server side and not the client side. There are legitimate non production use cases for turning off client authentication.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition if we allow this through I think we don't need the mock agent as the real agent can do what is necessary.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to add an enum setting to the proxy/main.go at this point for requiredAgentAuth? That way we can detect if the agent is meeting the minimum authentication requirements.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I brought this up because an incorrectly configured konnectivity-agent would send a large number of denied requests to the konnectivity-server. (agent retries + multiple threads hitting LB for regional clusters + CrashLoop retries).

Since there are use cases for turning off client authentication, removing this check is fine, but we should still think of ways to limit the outgoing requests of an incorrectly configured agent.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this validation

@cheftako
Copy link
Copy Markdown
Contributor

/assign @mikedanese
I would like to make sure Mike takes a look and approves prior to merge.

@k8s-ci-robot
Copy link
Copy Markdown
Contributor

@cheftako: GitHub didn't allow me to assign the following users: mikedanese.

Note that only kubernetes-sigs members, repo collaborators and people who have commented on this issue/PR can be assigned. Additionally, issues/PRs can only have 10 assignees at the same time.
For more information please see the contributor guide

Details

In response to this:

/assign @mikedanese
I would like to make sure Mike takes a look and approves prior to merge.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 27, 2020
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 3, 2020
Copy link
Copy Markdown

@caesarxuchao caesarxuchao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The gomock is cool. I wish I knew it earlier.

}
if o.authenticationAudience == "" {
return fmt.Errorf("authenticationAudience cannot be empty when agent authentication is enabled")
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also check if o.kubeconfigPath==nil?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It cannot be nil, since we have newProxyRunOptions().

sources:
- serviceAccountToken:
path: konnectivity-agent-token
audience: system:konnectivity-server No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this "audience" value gets encoded into the token?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

KubernetesClient.AuthenticationV1().TokenReviews() gets the audience is the parameters, so k8s API validates that token is issued with this audience

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But konnectivity-server calls TokenReviews, and this is the yaml for the konnectivity-agent.

My guess is the token data mounted by the agent will contain the "audience", and apiserver will be able to extract the "audience" out from the token.

@dberkov dberkov force-pushed the token branch 2 times, most recently from 7408e7e to c1c62a6 Compare February 4, 2020 17:05
@caesarxuchao
Copy link
Copy Markdown

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Feb 4, 2020
serverCount uint
// Agent pod's namespace for token-based agent authentication
agentNamespace string
// Agent pod's service account for token-based agent authentication
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we ever want different service accounts for different agents? Eg. agent service account per failure domain?

// all 4 parametes must be empty or must have value (except kubeconfigPath that might be empty)
if o.agentNamespace != "" || o.agentServiceAccount != "" || o.authenticationAudience != "" || o.kubeconfigPath != "" {
if o.agentNamespace == "" {
return fmt.Errorf("agentNamespace cannot be empty when agent authentication is enabled")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future we should consider accumulating these errors. Sort of annoying to be given and error I need a service account on run1 and then be given an error I need an audience on run2.

Copy link
Copy Markdown
Contributor

@cheftako cheftako left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the GKE reference.

@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Feb 6, 2020
Copy link
Copy Markdown
Contributor

@cheftako cheftako left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@cheftako
Copy link
Copy Markdown
Contributor

cheftako commented Feb 6, 2020

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Feb 6, 2020
@cheftako
Copy link
Copy Markdown
Contributor

cheftako commented Feb 6, 2020

/approve

@k8s-ci-robot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: cheftako, dberkov

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 6, 2020
@k8s-ci-robot k8s-ci-robot merged commit 65263a9 into kubernetes-sigs:master Feb 6, 2020
River-sh pushed a commit to River-sh/apiserver-network-proxy that referenced this pull request Sep 22, 2023
…odules/github.com/stretchr/testify-1.8.0

Build(deps): bump github.com/stretchr/testify from 1.7.5 to 1.8.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants