Setup private docker registry with anonymous pull access - docker

I'd like to setup a docker registry that allows anonymous pulls but authenticates pushes.
My naive approach was to allow get requests. But that seems to break the login as the client only creates the credentials if the initial Get request to /v2/ yields a 401.
However also repository reads start with that so I cannot put this behind authentication either.
Basically it seems I'd have to distinguish between a ping before a pull and a ping before a login.
I'm also happy to setup token authentication. But that would probably run into the same conundrum.

Apparently the way to go is to set up token authentication.
Then you can return a valid token for the scope pull even if no Basic Authentication was given.
You can find an example code on https://github.com/cloudfleet/floating-dock/blob/master/app/controllers/api/v1/jwt_controller.rb and https://github.com/cloudfleet/floating-dock/blob/master/app/services/auth/container_registry_authentication_service.rb
It is an adapted version of GitLabs JWT implementation for the registry.

Related

Keycloak - Permissions & Policy only works when using Evaluate tab

Our team is looking to use Policies/Permissions in Keycloak to grant scopes to a user when they log in, but only if they have a specific role.
I've gone through a couple tutorials and was successful in setting it up and testing it using the Evaluate tab (under Authorization). If my user has the specified role in my policy, the scope shows up in the token. When I remove the role, the scope does not show up.
That's all great. Our problem is that it doesn't work when I make an authentication code flow call using the same client (i.e. not using the evaluate tab). I never get any authorization section in my token at all...this only appears when I use the Evaluate tab.
I'll note that I've tried auth code flow calls requesting the scope as well as requesting the resource and also not requesting them. Same result...no authorization section at all in the generated token.
Am I missing something on how this functionality is supposed to work? Where could my gap be? TIA!
The token you obtain in the Evaluate tab is not an access token, it's an authorization token that Keycloak will issue to clients when they ask for permissions.
The access token you obtain via the authorization code flow will not contain permissions.
When using Keycloak Authorization Services, your clients will obtain permissions by requesting an authorization token from the Authorization REST API (cf: https://www.keycloak.org/docs/latest/authorization_services/#_service_obtaining_permissions)
You can do that manually or instead use a policy enforcer which is integrated in the Keycloak adapters :
Spring Boot : https://www.keycloak.org/docs/latest/securing_apps/#_spring_boot_adapter
Javascript : https://www.keycloak.org/docs/latest/authorization_services/#_enforcer_js_adapter
Quarkus : https://quarkus.io/guides/security-keycloak-authorization
etc..
There are lots of examples of what you want to achieve in the keycloak quickstart github repo. (folders starting by app-authz-*).
The spring boot adapter is not able to authorize the scope based resource policies correctly and there seems to be a bug.
Where as evaluate on admin UI does evaluate the scope based policies correctly.
I kind of hacked to get it working by creating different resources for each individual scope and then assigning policies. But thats not what it should be.

Authentication between docker containers in microservices architecture, bypassing JWT auth for internal calls

I have the following docker architecture, orchestrated with a docker compose:
Service1: Frontend application, react app
Service2: ExpressJS server
Service3: Django server
The three applications communicate with each other through HTTP API calls. There is no limit on who can call who. Every application is externally exposed
The user authenticates on the frontend application (Service1) and it resolves a JWT that can be later passed to every other subsequent call, every other service has then an authentication layer to validate the JWT calls.
My question is: How would we validate calls from Service2 to Service3 without any user activity (without JWT)?
This is required for crons or maintenance jobs.
My first solution was to create a docker network with a fixed subnet in our docker-compose, like this:
networks:
our-network:
ipam:
driver: default
config:
- subnet: "172.100.100.0/24"
Then, in Service2 and Service3, I allowed API calls coming from this subnet to be unauthenticated.
I worry this could be a security problem and wonder if there are any better solution.
A JWT token is typically signed with a private key belonging to the token issuer. It is a good practice that JWT-tokens as an issuer claim.
A JWT-token can typically be validated in two ways:
With a call to an OAuth token introspection endpoint of the issuer - but this adds more latency
Local validation with cached public key from the issuer - difficult to add logout functionality
If you use the cached solution, that does not add much latency, the JWT issuer must implement a OpenID Discovery endpoint including a reference to the JWKS endpoint where the issuer publishes its public key.
If you use Kubernetes, you can use a sidecar with OpenPolicyAgent that does the token validation for the app. It is not so fun for developers to implement token-validation functionality in every app, so this is an interesting alternative. You can also easyli add authorization rules with this solution.
How would we validate calls from Service2 to Service3 without any user activity (without JWT)?
When Service2 received the request from the user, authenticated with a JWT - it does the request to Service3 on-behalf-of the user, so it should pass the JWT token to Service3 as well - so that the Service3 can operate and only use resources that belong to the user, e.g. fetch from a database. This can be done without user intervention (until the JWT has expired).
This is required for crons or maintenance jobs
For Jobs - that is executed on-behalf-of the user, it is typically required to store a JWT-token with longer expiration time e.g. in a database. Typically this can be revoked by the user, and typically expire after 3 months or so, and then the user may need to authenticate again (or more than 3 months - depending on your needs). It is important that such token has lower permissions, typically only the permissions that is needed for the job.
It is late but I think the original question is still not answered.
What I usually do in such circumstances is that I create a "system user" and perform the operations on behalf of that special user. This enables to log such activities with the same framework if you do care.
From a security standpoint, you will want to restrict what this special user can do. And if those things are sensitive you will want to use super extra care on how a client service (service2 in your case) get access to the special user credentials.

Token delegation using LOGON32_LOGON_NETWORK_CLEARTEXT

How safe is it to use LOGON32_LOGON_NETWORK_CLEARTEXT?
We have the following scenario:
Web server A is using Win32 LogonUser. Then it needs to invoke an asmx method on server B.
If the used logon type is LOGON32_LOGON_INTERACTIVE it works well. However the customer rejects this because it requires interactive access.
If we use LOGON32_LOGON_NETWORK this does not allow token delegation to the remote server and we get 401 (as expected, according to the MSDN).
Attempting to use DuplicateToken to "upgrade" the token to interactive fails. This attempt was based on this article where it states:
"When you request an interactive logon, LogonUser returns a primary
token that allows you to create processes while impersonating. When
you request a network logon, LogonUser returns an impersonation token
that can be used to access local resources, but not to create
processes. If required, you can convert an impersonation token to a
primary token by calling the Win32 DuplicateToken function."
But it seems that if we use LOGON32_LOGON_NETWORK_CLEARTEXT as stated in this old thread, delegation works. But how safe is it for usage? According to MSDN:
"This logon type preserves the name and password in the authentication
package, which allows the server to make connections to other network
servers while impersonating the client. A server can accept plaintext
credentials from a client, call LogonUser, verify that the user can
access the system across the network, and still communicate with other
servers."
Are the credentials used in this format visible in anyway to sniffers (we're using Windows Integrated security, sometimes with SSL but not always).
Please advise.
I had the same question, and though I haven't found a definitive answer I've done some investigating and reading between the lines, and this is my conclusion (corrections welcome):
The ideal/safest use case is if your code looks like this pseudocode:
success = LogonUser(username, domain, password,
LOGON32_LOGON_NETWORK_CLEARTEXT, provider, out token)
if (success) {
StartImpersonation(token)
remoteConnection = AuthenticateToRemoteServer()
StopImpersonation()
CloseHandle(token)
// continue to use remoteConnection
}
The plaintext credentials associated with the LogonUser session will be destroyed when you close its handle (I haven't found a reference for this, but it doesn't make sense to me that they wouldn't). So for the lifetime of the token there was a copy of the user's credentials and it was used to authenticate to the remote server. But your application already had the credentials in memory in plaintext (in the variables username, domain and password) so this doesn't really present a additional security risk.
Any authentication with a remote server that uses Windows authentication will be using NTML or Kerberos and neither protocol sends the credentials on the wire, so that's not a concern. I can't say for sure what would happen if the remote server asked for basic authentication, but I think it's more likely that it would fail than your credentials would be sent over.
If you need to keep the token around longer, the documentation does state that the credentials are stored in plaintext (somewhere). I took a dump of a test process and wasn't able to find them in the dump file, so I don't know if that means that they are stored in kernel memory or what. I would be a little worried if I had to keep this token around for a long time.

Github API access to private repos using OAuth

Trying to access files in the private repositories of a Github organization of which I am a member, using the API. Tried a couple different ways so far:
1. If I use the username/password method --
curl -u "sashafklein:mypassword" https://api.github.com/repos/:org/:repo/git/trees/:file_sha
it works fine, but I'm trying to access the repos from a collaborative Rails app, so I don't want to publicize my github login credentials. I suppose creating a dummy GH account with access and using those credentials is possible, but it's definitely not ideal..
2. So I looked at the OAuth2 Secret/Key method in the API docs. But it doesn't work. If I curl the org repo url with my credentials as params in the url:
curl -i "https://api.github.com/orgs/:org/repos?private&client_id=<ID>&client_secret=<SECRET>"
Only the public repos show up. This may be a problem with how I'm passing params (passing "?private=true" should theoretically then return an empty list, but the list is identical and all public repos), but I'm following the docs.
3. So I got frustrated and took a look at these docs for getting a OAuth token, but I'm confused about how to alter it so that there's no user interface -- ie, so that my app has automatic access to the Github Orgs of which I am a member, without users of it having to do anything in particular.
Any ideas what I'm doing wrong with attempt 2, or how to get attempt 3 working automatically? I'm pretty stumped.
EDIT I think my client_id/secret are wrong, cause even when I use Octokit, it can't access the protected repos. Am I understanding this wrong? As me, I created an "Application" on Github for my Rails app, and I'm trying to use those credentials to access the org's private repos (to which I am a contributor) using the API.
In case anyone runs into this problem, here's the solution I found.
Apparently the client credentials I had weren't working. I think I didn't quite understand what they're for. The easiest way I could get this to work (ie, get permission for my rails app to access a private repo of which I was a member) was to use the username:password method (1, above).
So that my personal github credentials wouldn't be available to everyone using the app, I created a new dummy github account with access that serves exclusively as an api credentializer.
I am using Octokit with C# and encountered the same issue. After some investigation I found out it was a problem with my token permissions.
Token have scopes (https://developer.github.com/v3/oauth/#scopes) so to access private repositories you need 'repo' instead of 'public_repo' which I think was default.
This can be easily changed from Settings > Personal Access tokens > edit

Possible to Push src code to BitBucket repository using access token?

Is there anyway to Push source code to Bitbucket repo using access token.. If know kindly inform me guys.. Tnanks in advance guys..
I used below format to push the source code but it does not work for me.
git push https://x-token-auth:{access_token}#bitbucket.org
Yes, you can push to a repository using an OAuth 2 Bearer token. Note that this must be a valid OAuth 2 Bearer token. OAuth 1 Access tokens are not supported (as OAuth 1 requires each request to be signed individually).
The incomplete fragment you pasted looks ok, but the lack of output doesn't allow for more insightful feedback on what might be going wrong.
It might be best to contact us at support#bitbucket.org and share more details: the full shell output, the consumer key and where possible all HTTP headers (which you can get Git to dump to stdout using the GIT_CURL_VERBOSE=1 environment variable).
Before you contact us though, make sure you're using OAuth 2 (not 1) and that your bearer token is current (they expire after an hour and must then be refreshed) and that your token has the "repository" scope, which is required to access any repo data (check your OAuth Consumer page for this).
Here's the relevant documentation: https://developer.atlassian.com/bitbucket/concepts/oauth2.html
Yes it is possible to push your src code to BitBucket using accessToken via commandLine.
You can refer the developers BitBucket doc here

Resources