Skip to content
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

Azure plugin for client auth #43987

Merged

Conversation

ccojocar
Copy link
Member

@ccojocar ccojocar commented Apr 3, 2017

This is an Azure Active Directory plugin for client authentification. It provides an integration with Azure CLI 2.0 login command. It can also be used standalone, in that case it will use the device code flow to acquire an access token.

More details are provided in the README.md file.

kubernetes/kubectl#29

cc @brendandburns @colemickens

@k8s-github-robot k8s-github-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. release-note-label-needed labels Apr 3, 2017
@k8s-ci-robot
Copy link
Contributor

Thanks for your pull request. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please follow instructions at https://github.com/kubernetes/kubernetes/wiki/CLA-FAQ to sign the CLA.

Once you've signed, please reply here (e.g. "I signed it!") and we'll verify. Thanks.


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. I understand the commands that are listed here.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. label Apr 3, 2017
@k8s-ci-robot
Copy link
Contributor

Hi @cosmincojocar. Thanks for your PR.

I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with @k8s-bot ok to test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

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. I understand the commands that are listed here.

@k8s-reviewable
Copy link

This change is Reviewable

@0xmichalis 0xmichalis removed their assignment Apr 3, 2017
@ericchiang
Copy link
Contributor

ericchiang commented Apr 3, 2017

cc @kubernetes/sig-auth-pr-reviews @colemickens

"sync"
"time"

"github.com/Azure/go-autorest/autorest"
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like a net/http wrapper. Kubernetes already has a ton of these in tree. Is this required?

Copy link
Member Author

Choose a reason for hiding this comment

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

It is required. This is the base of the azure sdk, which contains the authentication package which is used by this plugin.


* Replace `USER_NAME` with your user name.

### Device Flow
Copy link
Contributor

@ericchiang ericchiang Apr 3, 2017

Choose a reason for hiding this comment

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

Are there some docs on what the technical details of this flow? That'd be very helpful when reviewing this PR. e.g. why a user would prefer this over the OpenID Connect client auth plugin.

Copy link
Member Author

Choose a reason for hiding this comment

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

Unfortunately I couldn't find some reasonable documentation for this flow. The big difference between client credentials and device code flows is that the JWT token acquired with the former one contains user information. It is a user token not a client token. The claims form this token can be used later for role-based access control.

This flow is suited for CLI tools. e.g. Azure CLI makes use of it in order to acquire user tokens.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Anyway, doesn't Google do something similar with a gcloud specific plugin?

In Azure's case, the actual id_tokens produced by AADv1 (at least after refresh) are not signed and thus not usable for this scenario. Hence the use of the access_token presumably - but again, that's the same thing the Google plugin does when it reads the access token from the json response from gcloud config config-helper.

Copy link
Contributor

Choose a reason for hiding this comment

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

Google's GCP plugin signs a JWT but the format is somewhat propitiatory to GCP. They use webhook auth to process the token on their end, they don't use the OpenID Connect plugin.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, I forgot I learned that a couple weeks ago...

```
kubeclt get pods

To sign in, use a web browser to open the page https://aka.ms/devicelogin and enter the code DEC7D48GA to authenticate.
Copy link
Member

Choose a reason for hiding this comment

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

is DEC7D48GA just an example?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is fake code number.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this prompt triggered by kubectl directly? What happens if it's not in an interactive session? I'd expect these kind of flows to be handled by az login

Copy link
Member Author

Choose a reason for hiding this comment

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

There are two scenarios:

  1. The user logs in with az login which stores the tokens in ~/.azure/accessToken.json file. The azure plugin will read the tokens from this file and refresh them if needed using the client_id also from the same file.

  2. If the plugin does not find any az file available. It will start the device flow by prompting to the use the device code retrieved from AAD and waiting for use to login. The user will login with AAD in a browser by providing the device code. Finally the plugin will receive the tokens directly from AAD.

Note that in both cases the tokens are stored in the kubernetes configuration. Next time when the kubectl is executed, it will read the token from kubernetes config first.

@ccojocar
Copy link
Member Author

ccojocar commented Apr 4, 2017

I signed it!

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. and removed cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. labels Apr 4, 2017
@colemickens
Copy link
Contributor

This requires the user to auth every hour, right?

Copy link
Contributor

@colemickens colemickens left a comment

Choose a reason for hiding this comment

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

Few typos + a question about using accessToken for AuthN

}, nil
}

func (ts *azureTokenSourceFromFile) isTeantAuthroity(authority string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: Teant


func newAzureTokenSourceDeviceCode(clientID string, tenantID string, audience string) tokenSource {
return &azureTokenSourceDeviceCode{
clinetID: clientID,
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: clinet

2. Configure the `apiserver` to use the Azure Active Directory as an OIDC provider with following options

```
--oidc-client-id="https://management.core.windows.net/" \
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this also be parameterized as "APPLICATION_ID" in case the user chooses to use a different client_id below? Otherwise how does the token validation work?

Copy link
Member Author

Choose a reason for hiding this comment

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

Apparently the apiserver expects the client id to be the same like the audience. Actually apiserver which plays the role of a resource server does not need a valid client id. It only has to download the public keys of the identity provider in order to verify the signature of the token.

Copy link
Contributor

Choose a reason for hiding this comment

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

Does azure embed this as the audience? Isn't that claim supposed to be set as the client-id?

Copy link
Member Author

Choose a reason for hiding this comment

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

The audience should be different than the client ID. The audience is typically a URI of a rest-endpoint or a UUID.

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess the clean fix is to have two options, one for client id and other one for audience. The appiserver should verify the audience from the token against the whitelisted value provided in the option.

Copy link
Contributor

Choose a reason for hiding this comment

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

The audience should be different than the client ID.

Why do you say this? That's not my understanding or expectation. With real id_token, the audience is the client_id. See: https://github.com/colemickens/azure-ad-k8s-oidc-example

Copy link
Contributor

Choose a reason for hiding this comment

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

(and even though that example is AADv2, the same is true of id_tokens issued to AADv1). The example works as normal, with normal client_id (not the resource value), etc.

Copy link
Member Author

@ccojocar ccojocar Apr 5, 2017

Choose a reason for hiding this comment

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

Let's take an example. I have a resource application registered with AAD for apiserver which has the resourceAppId fdfb78c2-788c-4ab6-bbed-cfd89cd21025. This will be provided in the --oidc-client-id. Now if I need to acquire a token for this application, another client application must be registered wiht appId 319e3b43-c214-43e8-8d8d-8d33b8e47902 which has delegated permissions to the apiserver application.

I can request a token with the following values:

  • applicatoinId: 319e3b43-c214-43e8-8d8d-8d33b8e47902
  • tenantId:
  • resource: fdfb78c2-788c-4ab6-bbed-cfd89cd21025

The returned token will have these claims (many claims ignored for brevity):

{
"aud": "spn:fdfb78c2-788c-4ab6-bbed-cfd89cd21025",
 "iss": "https://sts.windows.net/26f087ba-1a21-11e7-93ae-92361f002671/",
 "appid": "319e3b43-c214-43e8-8d8d-8d33b8e47902"
}

azure cli does the same but the audience is an URL:

{
"aud": "https://management.core.windows.net/",
 "iss": "https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/",
  "appid": "04b07795-8ddb-461a-bbee-02f9e1bf7b46"
}

As you see from the first example the audience can be almost the same like the client id if one uses the UUID of the resource when acquiring the token.

Note that any owner of an application can set delegated permissions to any public resource application registered in the same AAD. The conclusion is that the RBAC policy should be based on the user and group claims. The audience does not have strong security guarantees.

Copy link
Contributor

Choose a reason for hiding this comment

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

The audience should be different than the client ID.

No, this is totally against the OpenID Connect spec[0]

[0] https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation

Copy link
Member Author

Choose a reason for hiding this comment

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

I get you point a client needs to request a token for itself. In that case AAD will return:

{
  "aud": "spn:319e3b43-c214-43e8-8d8d-8d33b8e47902",
  "iss": "https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/",
   "appid": "319e3b43-c214-43e8-8d8d-8d33b8e47902",
}

Are you fine if the oidc-id is configured to spn:319e3b43-c214-43e8-8d8d-8d33b8e479021?

@ericchiang @colemickens
I guess, the azure cli integration has to be removed because it adhere to OAuth2 actors model (https://nordicapis.com/api-security-oauth-openid-connect-depth/) requesting always a token for a resource server not for itself.

I can keep the device code and also remove the audience configuration.

kubectl config set-credentials "USER_NAME" --auth-provider=azure \
--auth-provider-arg=client-id=APPLICATION_ID \
--auth-provider-arg=tenant-id=TENANT_ID \
--auth-provider-arg=audiance=https://management.core.windows.net/
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: audiance

Copy link
Member Author

Choose a reason for hiding this comment

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

@colemickens Thank you for review! I fixed the typos.

req2.Header[k] = append([]string(nil), s...)
}

req2.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.token.AccessToken))
Copy link
Contributor

Choose a reason for hiding this comment

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

Am I right in understanding this is using an accessToken as an OIDC token?

My understanding is that this was discouraged: https://oauth.net/articles/authentication/

But I think the Google auth works this same way, by taking the CLI access token and using it as an OIDC token...

Copy link
Contributor

Choose a reason for hiding this comment

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

cc: @ericchiang can you share any thoughts on this too?

Copy link
Member Author

Choose a reason for hiding this comment

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

In AAD the access token is equivalent with id token. It is a JWT token with all claims of a user.

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess I'm still pretty confused as to how this conforms to OIDC, or is secure in its usage. To be clear, as far as I can tell, it seems to be the same pattern that Google uses... but it seems invalid with my understanding of OIDC.

Consider: If the client_id is not validated, and any old access token can be used, it means that I can take accessTokens granted to me via any application and then use them to talk to your apiserver? That seems... potentially very bad. Or am I misunderstanding? Doesn't this mean my personal application that lets users do OAuth flow to let me create some things in their subscription... can't I now turn around and use those scoped access tokens to get access to some disparate Kubernetes clusters that just happen to be configured for the same tenant without the user's consent?

This is sort of the scenario discussed in the link above that discourages the use of accessTokens for AuthN...

Copy link
Contributor

Choose a reason for hiding this comment

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

Consider: If the client_id is not validated, and any old access token can be used, it means that I can take accessTokens granted to me via any application and then use them to talk to your apiserver? That seems... potentially very bad.

Yes, it is extremely weird that the oidc-client-id is not set to a unique client_id.

Why can't we just use the id_token directly?

Copy link
Contributor

Choose a reason for hiding this comment

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

AADv1 doesn't sign id_token when they're refreshed - meaning user would have to do device auth every hour - regardless of if kubectl was retrieving directly, or if we forced user back to az.

AADv2 lacks this entire device flow.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is right the id_token issued by AAD cannot be used to verity the access, but as I said the access token contains the same claims.

It is a bit strange how the appiserver validates the audience. The identity provider will request consent to a user for a specific audience when issuing the token. In this case should be a dedicated audience for kubernetes apiserver which should be registered in the identity provider as resource server.

The issue is in CorsOS's go-oidc package which is used by the oidc plugin of apiserver. It property verifies the signature, expiration but it does the following assumption on audience.

https://github.com/coreos/go-oidc/blob/master/oidc/verification.go

Code snippet from VerifyClaims function

	// aud REQUIRED. Audience(s) that this ID Token is intended for.
	// It MUST contain the OAuth 2.0 client_id of the Relying Party as an audience value.
	// It MAY also contain identifiers for other audiences. In the general case, the aud
	// value is an array of case sensitive strings. In the common special case when there
	// is one audience, the aud value MAY be a single case sensitive string.
	if aud, ok, err := claims.StringClaim("aud"); err == nil && ok {
		if aud != clientID {
			return fmt.Errorf("invalid claims, 'aud' claim and 'client_id' do not match, aud=%s, client_id=%s", aud, clientID)
		}
	} else if aud, ok, err := claims.StringsClaim("aud"); err == nil && ok {
		if !containsString(clientID, aud) {
			return fmt.Errorf("invalid claims, cannot find 'client_id' in 'aud' claim, aud=%v, client_id=%s", aud, clientID)
		}
	} else {
		return errors.New("invalid claim value: 'aud' is required, and should be either string or string array")
	}

Copy link
Contributor

Choose a reason for hiding this comment

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

@cosmincojocar the audience shouldn't be the API server, it should be whatever the client_id of the client that initiated the login flow to request an ID token. That's specifically called out in the docs. The API server is NOT a client. It's set up to only allow ID tokens issues for a single client.

As for that snippet, it's just implementing the spec[0]

  1. The Client MUST validate that the aud (audience) Claim contains its client_id value registered at the Issuer identified by the iss (issuer) Claim as an audience. The aud (audience) Claim MAY contain an array with more than one element. The ID Token MUST be rejected if the ID Token does not list the Client as a valid audience, or if it contains additional audiences not trusted by the Client.

The issue seems to be the aud embedded in your access token, which is https://management.core.windows.net/ rather then your client_id.

[0] https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation

@ccojocar
Copy link
Member Author

ccojocar commented Apr 4, 2017

@colemickens The user will authenticate only once, then the plugin will use underneath the refresh token every hour to fetch a new access token. I would say from usability perspective this is quite nice.

Copy link
Contributor

@colemickens colemickens left a comment

Choose a reason for hiding this comment

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

This change looks fine, but I don't understand if OIDC is being used appropriately in K8s right now, I've left a comment about it. Maybe @ericchiang can fix my understanding of OIDC and/or why it's okay to use accessTokens.

Please do see the note about Authority URL. ACS-Engine is deploying working clusters in GermanyCloud/ChinaCloud, so it would be good if this integration were to "just work" there as well.


const (
azureTimeFormat = "\"2006-01-02 15:04:05.99999\""
azureAuthority = "https://login.microsoftonline.com"
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you not hard code this? This will fail in Germany/China clouds.

Copy link
Contributor

Choose a reason for hiding this comment

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

You have the real (full tenant) authority URL in the tokens json anyway, I believe.

Copy link
Member Author

Choose a reason for hiding this comment

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

I removed the hardcoded authority URL. It is read anyhow from file. Also the Azure environment is now configurable for device code flow.


* Replace `USER_NAME` with your user name.

### Device Flow
Copy link
Contributor

Choose a reason for hiding this comment

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

Anyway, doesn't Google do something similar with a gcloud specific plugin?

In Azure's case, the actual id_tokens produced by AADv1 (at least after refresh) are not signed and thus not usable for this scenario. Hence the use of the access_token presumably - but again, that's the same thing the Google plugin does when it reads the access token from the json response from gcloud config config-helper.

req2.Header[k] = append([]string(nil), s...)
}

req2.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.token.AccessToken))
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess I'm still pretty confused as to how this conforms to OIDC, or is secure in its usage. To be clear, as far as I can tell, it seems to be the same pattern that Google uses... but it seems invalid with my understanding of OIDC.

Consider: If the client_id is not validated, and any old access token can be used, it means that I can take accessTokens granted to me via any application and then use them to talk to your apiserver? That seems... potentially very bad. Or am I misunderstanding? Doesn't this mean my personal application that lets users do OAuth flow to let me create some things in their subscription... can't I now turn around and use those scoped access tokens to get access to some disparate Kubernetes clusters that just happen to be configured for the same tenant without the user's consent?

This is sort of the scenario discussed in the link above that discourages the use of accessTokens for AuthN...

@liggitt liggitt assigned colemickens and ericchiang and unassigned pmorie Apr 5, 2017
@liggitt
Copy link
Member

liggitt commented Apr 5, 2017

@colemickens @cosmincojocar I've added this to the agenda for the sig-auth call tomorrow (4/5) if either of you are able to join (I know it's not a convenient time in Zürich, sorry...); might be faster to talk through how this fits into kubectl and azure auth in person.

@ccojocar
Copy link
Member Author

ccojocar commented Apr 5, 2017

@colemickens Not any token will be accepted by apiserver. First of all they need to be signed by AAD and not expired. Also they need to be requested for the audience provided in the --oidc--client-id options (e.g. https://management.core.windows.net/). You can consider this as a sort of whitelist.

The access can be also narrowed down by using the role based access control provided by Kubernetes. The username and groups claims can be provided in the --oidc-username-claim and respectively --oidc-groups-claim. Now image if you build the access policies based on the group claims, then the token will need to have a certain set of groups in order to get access to the Kubernetes's API. In the end a user can have these groups claims only if an admin assigns them to her in AAD.

@colemickens
Copy link
Contributor

Per the discussion in sig-auth this morning, there is no precedent for having the kubectl auth plugin do an interactive flow. Instead, the Azure CLI needs to have a command that will return a properly refreshed token available to use. I've filed a feature request on az for this: Azure/azure-cli#2774

@grodrigues3 grodrigues3 added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Apr 5, 2017
@ccojocar
Copy link
Member Author

ccojocar commented Apr 5, 2017

I removed the Azure CLI integration and configured the client to fetch a token for itself. The device code message is promoted only if no tokens are already present in the kubecl configuration.

This is a better user experience than manually fetching the id_token and storing it in the configuration.

@colemickens
Copy link
Contributor

My understanding of the feedback in the sig-auth call is that there should be NO interactive dialogs in the kubectl plugin - so sort of the opposite of the change that you made. The point made was that all of the actual token retrieval mechanism is delegated such that kubectl is not in the business of doing the auth handshake itself - instead, it just os.Execs az (or in Google's case gcloud config config-helper). Also, I'm a bit confused why there's now discussion of id_token since, as I understand it, you're not using the id_token but rather the accessToken.

If you look at a real id_token, the fields all just line up the way they're supposed to. None of this spn: prefix, or using the resource URI as the audience or anything like that. The deviation from the expectations I have from the OIDC standard and from my experiments with real id_tokens + AAD + Kubernetes makes me nervous about approving this sort of change without input from other folks. At the very least, I would want @ericchiang's blessing.

@ericchiang Somewhat tangentially... Is there anyway we can get more information about the internals of the service that Google uses with the webhook authenticator? How are y'all safely validating accessTokens for authentication purposes? If it's something you're unable to discuss publicly but would be willing to share some details on privately, we could try to setup another video chat with the three of us?

@ccojocar
Copy link
Member Author

ccojocar commented Apr 7, 2017

I don't quite get this argument interactive vs non-interactive flow. What is the advantage of delegating the authentication to an external tool (e.g. az) which is called as a process from the plugin? This tool most like will execute the same kind of flow. The error handling looks a bit fragile to me, the plugin will rely only on the exit code of the tool and probably will have to parse the stderr/stdout in order to get more details about the error. Why not using directly the Go library to achieve the same?

The user of this plugin has also the choice to set manually the tokens in the configuration and in that case the interactive flow will not be executed.

The confusion regarding the access_token vs id_token is because we compare AAD v1 with AAD v2. The id_token which you are talking about is issued by AAD v2, which is compatible with OIDC specs. A client will request some scopes not an access_token for a resource like in v1. If we compare the claims of the id_token from v2 vs access_token from v1, they are pretty much on par, excepting the audience which has the spt: prefix that stands from service principal.

This plugin requests tokens from AAD v1. I guess is more the question: Do we want to support AAD v1 which is OAuth 2.0 but not OIDC compatible? The access_token issued by v1 has a different meaning than an id_token issued by v2. In v1 case, a client will acquire an access token for a service principal/resource which in our case is apiserver (which should have its own UUID in AAD v1), while in v2 case, a client will request some scopes for its token.

@ericchiang
Copy link
Contributor

@cosmincojocar I hadn't seen a comment addressing client_secret auth flow. Did you want to add it in this PR?

@ccojocar
Copy link
Member Author

@ericchiang I would prefer that we close this PR since it got quite long. I will follow with another PR for client_secret auth.

@ericchiang
Copy link
Contributor

Going to wait for @colemickens' comment. Other than that lgtm.

@ericchiang
Copy link
Contributor

bump. since freeze is friday I'm going to advocate we merge as is. any objections?

@colemickens
Copy link
Contributor

/lgtm I'm fine with merging as is and adding client_secret auth later

@colemickens
Copy link
Contributor

/assign @lavalamp

@ericchiang
Copy link
Contributor

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 31, 2017
@ccojocar
Copy link
Member Author

ccojocar commented Jun 1, 2017

@k8s-bot pull-kubernetes-e2e-gce-etcd3 test this

@ccojocar
Copy link
Member Author

ccojocar commented Jun 5, 2017

@k8s-bot test this

@ericchiang
Copy link
Contributor

Let me figure out if we made/how we make 1.7 for this.

@ccojocar
Copy link
Member Author

ccojocar commented Jun 7, 2017

Any chance to get this merged?

@ericchiang
Copy link
Contributor

@cosmincojocar This wasn't approved when the 1.7 freeze came down. I think we're out of luck.

@brendandburns
Copy link
Contributor

/approve

@brendandburns brendandburns modified the milestones: v1.8, v1.7 Jun 13, 2017
@k8s-github-robot k8s-github-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 13, 2017
@brendandburns
Copy link
Contributor

/approve

I'm approving this for 1.7 since it was LGTM the day before code freeze. @dchen1107 for visibility.

This is low risk since it is a plugin and off by default.

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: brendandburns, colemickens, cosmincojocar, ericchiang

Associated issue: 29

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

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-ci-robot
Copy link
Contributor

k8s-ci-robot commented Jun 13, 2017

@cosmincojocar: The following test failed, say /retest to rerun them all:

Test name Commit Details Rerun command
Jenkins GCE e2e f5dcc92 link @k8s-bot cvm gce e2e test this

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

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. I understand the commands that are listed here.

@brendandburns
Copy link
Contributor

/retest

@k8s-github-robot
Copy link

Automatic merge from submit-queue (batch tested with PRs 46441, 43987, 46921, 46823, 47276)

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. release-note Denotes a PR that will be considered when it comes time to generate release notes. 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.