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

Allow websocket authentication via protocol header #14716

Merged
merged 3 commits into from
Jun 27, 2017
Merged

Allow websocket authentication via protocol header #14716

merged 3 commits into from
Jun 27, 2017

Conversation

liggitt
Copy link
Contributor

@liggitt liggitt commented Jun 17, 2017

Browsers do not have the ability to set headers programatically on websocket requests, all they have control over is the URL and the websocket protocols sent. Previously, we passed a bearer token as a query parameter. This PR adds support for specifying a bearer token via a websocket protocol instead, which moves it into the request headers.

Format is base64url.bearer.authorization.k8s.io.<base64url-encoded-token>

Base64-encoding the token is required, since bearer tokens can contain characters a websocket protocol may not (/ and =)

fixes https://bugzilla.redhat.com/show_bug.cgi?id=1458283

docs PR is openshift/openshift-docs#4659

@liggitt
Copy link
Contributor Author

liggitt commented Jun 17, 2017

[test]

@liggitt
Copy link
Contributor Author

liggitt commented Jun 19, 2017

@enj @simo5 PTAL

if !utf8.Valid(decodedToken) {
return nil, false, errors.New("invalid token bytes")
}
token = string(decodedToken)
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like getting to this point more than once should be a failure.

// auth is the token authenticator to use to validate the token
auth authenticator.Token
// remove indicates whether the protocol with the token should be stripped from the incoming request
remove bool
Copy link
Contributor

Choose a reason for hiding this comment

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

Why would anyone set this to false?


user, ok, err := a.auth.AuthenticateToken(token)
if ok && a.remove {
req.Header.Set(protocolHeader, strings.Join(filteredProtocols, ","))
Copy link
Contributor

Choose a reason for hiding this comment

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

Link to the spec that indicates that repeating the header is equivalent to having the header once with a comma delimited list?

}

var (
// connectionUpgradeRegex matches any Connection header value that includes upgrade
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't we already have an isUpgrade function somewhere?

@deads2k
Copy link
Contributor

deads2k commented Jun 19, 2017

open upstream so we only have to choose the protocol prefix once and don't end up with backward compatibility issues?

@liggitt
Copy link
Contributor Author

liggitt commented Jun 21, 2017

[test]

@enj
Copy link
Contributor

enj commented Jun 21, 2017

cc @openshift/security

Copy link
Contributor

@enj enj left a comment

Choose a reason for hiding this comment

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

More duplicate code.

tokenAuthenticators,
bearertoken.New(serviceAccountTokenAuthenticator),
websocket.NewProtocolAuthenticator(serviceAccountTokenAuthenticator),
paramtoken.New("access_token", serviceAccountTokenAuthenticator, true),
Copy link
Contributor

Choose a reason for hiding this comment

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

paramtoken.New has duplicate isWebSocketRequest logic.

@openshift-bot
Copy link
Contributor

openshift-bot commented Jun 26, 2017

continuous-integration/openshift-jenkins/test Waiting: Determining build queue position


var protocolHeader = textproto.CanonicalMIMEHeaderKey("Sec-WebSocket-Protocol")

var invalidToken = errors.New("invalid bearer token")
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: errInvalidToken by convention

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will open follow-up upstream, but I don't plan to pick it here... we'll get both in the 1.8 rebase

@smarterclayton
Copy link
Contributor

Surprisingly small change, I like it.

"k8s.io/apiserver/pkg/util/wsstream"
)

const bearerProtocolPrefix = "base64url.bearer.authorization.k8s.io."
Copy link
Contributor

Choose a reason for hiding this comment

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

A little weird for this to be a prefix, rather than the suffix

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to make it base64url.bearer.authorization.k8s.io/... but all reasonable separator characters are disallowed. Already merged upstream... feel strongly enough to revisit it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I mean I have a mild preference for ordering and we will never change it. Up to you, don't feel that strongly.

I'm going to leave it as-is. It's more readable with it as a prefix, and since the point of namespacing is to avoid conflicts, and the rest of the data contains enough entropy to authenticate, conflicts are a non-issue.

@smarterclayton
Copy link
Contributor

smarterclayton commented Jun 27, 2017 via email

@liggitt
Copy link
Contributor Author

liggitt commented Jun 27, 2017

[merge]

@openshift-bot
Copy link
Contributor

openshift-bot commented Jun 27, 2017

continuous-integration/openshift-jenkins/merge Waiting: You are in the build queue at position: 3

@openshift-bot
Copy link
Contributor

Evaluated for origin merge up to 2c2e649

@deads2k
Copy link
Contributor

deads2k commented Jun 27, 2017

re[test] since the API move happened

@openshift-bot
Copy link
Contributor

Evaluated for origin test up to 2c2e649

@openshift-bot
Copy link
Contributor

continuous-integration/openshift-jenkins/test FAILURE (https://ci.openshift.redhat.com/jenkins/job/test_pull_request_origin/2701/) (Base Commit: c7d9fb8) (PR Branch Commit: 2c2e649)

@liggitt
Copy link
Contributor Author

liggitt commented Jun 27, 2017

flake on #14857, green otherwise

@deads2k
Copy link
Contributor

deads2k commented Jun 27, 2017

No conflicts since base, lgtm. merging to get a good pick level

@deads2k deads2k merged commit 53b1acb into openshift:master Jun 27, 2017
@liggitt liggitt deleted the websocket-auth branch June 27, 2017 17:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants