Control and governance around PAT in VSTS - azure-devops

We are evaluating VSTS for an enterprise use.
One of the challenges from security team is lack of control and governance around usage of PAT (personal access tokens)
As I understand, any user can create one or more PAT and this PAT could be used from outside network to make REST API calls (or to connect with tools outside network) to VSTS to access information.
Have number of questions around this scenario and any insights/ workarounds from your experience are appreciated
How is your organization handling this issue or has worked around this issue? Looking for options to get buy-in from security team. Has anyone ever approached Microsoft with this problem statement? I am sure there are many enterprise customers, wondering how did they tackle this issue.
Is there a way to disable creation of PAT for all users? Don't see any option, but any workaround to enforce this.
Is there a way to get list of all PATs across all users? Don't see any option in VSTS, but may be through a script of some sort
Thanks

Update
There is now an API to list which PATs have been created and the option for an admin to revoke PATs on behalf of their users:
GET https://vssps.dev.azure.com/{organization}/_apis/tokenadmin/personalaccesstokens/{subjectDescriptor}?api-version=5.0-preview.1
Response:
{
"value": [
{
"clientId": "00000000-0000-0000-0000-000000000000",
"accessId": "00000000-0000-0000-0000-000000000000",
"authorizationId": "952858d3-7084-4635-964e-3c2a57645185",
"hostAuthorizationId": "00000000-0000-0000-0000-000000000000",
"userId": "bb5bb6c8-ef0a-400f-8987-92b3674d2043",
"validFrom": "2018-07-19T00:00:00",
"validTo": "2018-07-19T00:00:00",
"displayName": null,
"scope": "app_token",
"targetAccounts": null,
"token": null,
"alternateToken": null,
"isValid": true,
"isPublic": false,
"publicData": null,
"source": null
},
....
More details here:
https://learn.microsoft.com/en-us/rest/api/azure/devops/tokenadmin/personal%20access%20tokens/list?view=azure-devops-rest-5.0
And to revoke tokens of other users then use:
POST https://vssps.dev.azure.com/{organization}/_apis/tokenadmin/revocations?api-version=5.0-preview.1
[
{
"authorizationId": "532c7fe6-74f8-408b-8051-4abb73dca491"
}
]
See:
https://learn.microsoft.com/en-us/rest/api/azure/devops/tokenadmin/revocations/revoke%20authorizations?view=azure-devops-rest-5.0
There is an option to turn off Basic Credentials/Alternate authentication and SSH credentials, which are less secure than personal access tokens. There is no option to turn off Personal Access Tokens. I suppose the primary reason for this is that Git and the VSTS Agent infrastructure rely on these access tokens to work.
Since the Personal Access Tokens can be restricted in their scope, they're actually more secure than caching the user's credentials directly. They can also never give more permissions than the user already has.
You can't query all personal access tokens for all users, that would be a huge security violation. Exactly for the reason you're trying to restrict access to these tokens.
You can disable OAuth and Basic Credentials. This will not block Personal Access Tokens:
https://learn.microsoft.com/en-us/vsts/accounts/change-application-access-policies-vs?view=vsts
Impact on Azure Conditional Access is explained here:
https://learn.microsoft.com/en-us/vsts/accounts/manage-conditional-access?view=vsts
Important
VSTS only enforces conditional access policies when a user signs into services with their AAD credentials. Accessing VSTS using personal access tokens (PATs), alternate authentication, OAuth, and SSH keys circumvents conditional access policies.
Remember that when a person performs authentication using Azure Conditional Access and then leaves the building will be able to use that credential until it expires. In the end, security comes from education and monitoring, not from trying to put everything in an airtight container.
VSTS does keep an activity log which includes which users have performed which actions. This log will include the user's IP address. This way you can at least monitor the actions.

Related

Get Organization of a PAT Azure DevOps API

Given an Azure Devops Personal Access Token having access to only 1 Organization, is it possible to fetch which Organization it has access to using the API? Like an introspection endpoint?
Notes:
there is an endpoint listing accounts of a specific user but this requires a PAT with access to all organization (although it is not documented) which is too permissive for my usecase
there is the endpoint listing tokens of the account but it requires a specific tokenAdministration scope which too permissive for my usecase
Based on my knowledge there is currently no direct way to know which organization a PAT has access to.
There are two workarounds you can refer to:
Using this REST API Pats - List to list all PATs in one organization. You need to use OAuth authentication. Then check if your current PAT is in it.
As Vince Bowdren said, use your PAT to try to access the organization, like call some REST APIs, then you know which organization the PAT belongs to. But this is not necessarily successful, because it is related to the scope of your PAT. For example, your PAT belongs to an organization, but the scope of your PAT does not meet the requirements of the API you use.

Realm policies are being ignored while getting token

I have two realms, a public webapp and an extranet where only employees can access.
I have tried setting group policies.
When I try to connect with an non-employee user, keycloak still returns the access token.
What did I miss?
EDIT.
I made a mistake, I only have 2 clients.
You have to limit the access granted to your access token to achieve this. There are three ways to do it (that I know of)
Audience: Allows listing the resource providers that should accept an access token.
Roles: Through controlling what roles a client has access to, it is
possible to control what roles an application can access on behalf
of the user.
Scope: In Keycloak, scopes are created through client scopes, and an
application can only have access to a specific list of scopes.
You can look at this example which explains the flow on how to achieve this using role based method. You can refer this as well.

How to find out which user a given Azure DevOps token (PAT) belongs to?

Occasionally we encounter an Azure DevOps pipeline or piece of code using a token nobody knows where it came from. This should not happen, of course, but by times reality differs from an ideal world.
If I only have an Azure DevOps "Personal Access Token", how can I find out which user it belongs to?
Unfortunately, I am afraid you can't find out which user a PAT belongs to.
The PAT(personal access token) will not be exposed anywhere after you create it, it will just be stored in the database on Microsoft side.
Also, you could not get the related information via the personal access token itself, at most you can use the REST API - Pats - Get to get the PAT related information(e.g. displayname, targetAccounts, etc) via the authorizationId, but if you just have the token itself, you could not fetch the authorizationId firstly.
curl -u :{PAT} https://dev.azure.com/{organization}/_apis/connectionData | jq

Create my own AccessTokens with MS Identity Platform

I am in the process of expanding our login options on our product to support MS Identity Platform, to be able to use Azure AD login (and gain SSO/MFA with that)
Currently we are using .Net Core + JWT (JwtBearerDefaults.AuthenticationScheme)
The environment is angular clients, .Net Core APA, and a back-end database.
I have the setup working.
My challenge is that in our business model and backend database we have ~2.000 userrights and our own User/Role model granting access.
I am currently getting the IdToken from MSAL and in my proof of concept using the oid to couple the Azure ID with our User model.
But, in our existing JWT solution, our access token holds claims about the User Id, but also the role, and another property (Unit/Vessel) determining access. From these three properties we can verify against the 2.000 userights on API side whether or not a request is allowed or not.
I would like to keep this information (User, Role, Unit) in the token - but have doubts on how.
Constraints:
We cant create/use Azure claims. We have too many, and customers will manage the Azure application - while we create, add, remove rights for each version of our software.
Azure don't know about role/unit data - and these are different for each customer - so that information can't be in Azure either.
My best idea is outlined below - would this approach be correct, and live up to the way ID/Access is separated?
I hope someone can give me some feedback on this.
My idea is, that the Angular client gets the Azure IDToken. I then use the Azure IDToken, call our API, which on server side, validates ID Token, and then grants me an access token, which contains the user, role and unit. This token is not Azure'd at all, just a token generated by our API - which again will be the only one validating it). Pro's on this approach is also I can keep one type of Access Token, no matter which IDToken is supplied by Azure or our own API.
Tried to outline the flow below in this DrawIO diagram.
I hope someone with more experience in the Token field can validate if this would be a viable approach?
Best regards
/Anders
This is a viable approach except for one thing.
Do not use Id token for authorization.
Your front-end should acquire an access token from AAD for your back-end.
This access token contains the user objectId, allowing you to map the user to a user in your database.
An Id token is only meant for the application that requested authentication and tells it metadata on the user like their display name etc., but it is not meant for authorizing anything.

Exposing Cognito Protected AWSGateway APIs to clients

Use-case:
We have a few AWSGateway APIs which our clients can use to do somethings in the backend. These APIs are Cognito protected. Currently our clients are using this APIS through an android app which was built using Cognito Mobile SDKs.
Now we are trying to expose these APIs to our clients to be integrated into their internal workflows.
I was trying to find what is the best way to do this. Currently I am not able to find any resources on how to do this.
I have seem the server side user of AWS Cognito but I don't think that is what we want to do here.
Thanks.
To answer your question correctly we need more information.
Can the internal workflows be configured to use REST Services?
What authentication processes does the internal workflows support?
SDK or no SDK
You can access the webservices in API Gateway via a generated SDK or your own code.
Instructions to generate an SDK from the API Gateway Console are found here.
To invoke the webservice with authentication can be done in four ways IAM, API Keys, Cognito, custom authoriser. I am going to mention the first three.
IAM
Step 1, create a user in IAM with an access key and secret key.
Step 2, is too setup a role to access the API using IAM. Go to
IAM, select roles, create a role, and grant it access to your
API Gateway functions. Which would look something like this:
Sample IAM Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::account-id:user/Alice",
"account-id"
]
},
"Action": "execute-api:Invoke",
"Resource": [
"arn:aws:execute-api:region:account-id:api-id/stage/GET/pets"
]
}
]
}
allocate this role to the user you created. Policy examples are available here.. For more authentication options that include local certificates etc look here.
Step 3, call the API using the AWS Secret and Key SDK.
API Keys
If you add keys to your APIs the mobile app will fail as it does not have these keys. It would be best to deploy a different version of your APIs that could wrap the existing ones, could provide additional functionality specific to the workflow. To find out how to do this follow this link.
The advantage of API keys are that you can throttle access to your API Gateway functions, remove the keys at will, recycle them etc.
Cognito - Federated Users
Your mobile users are actually authenticating using federated users. However, one of the federated user channels happens to be cognito. You can add more, OpenAuth, Google, Facebook, SAML, etc, here you could add the Authentication type used by your client. A user would then use their username and password, to authenticate to the clients security provider, those credentials are then passed through to the API via federated users, and therefore federated users must be setup to use the same authentication mechanism as your client. See the following blog post
For this solution we have multiple options. 1. Pass the user credentials through to the API with federated users, this assumes the users interface calls the webservice but as you mentioned it is workflow, and I assume the user does not access the service directly as they do with the mobile application. i.e. services are called by a machine as a background process on a server. Which means this solution will not work. Option 2. is to create a new user, in cognito for the client. This is the same as accessing the service via the mobile app. To do this needs a little work extra work on the client as you need to retrieve the temporary access tokens.
Step 1. Use the SDK, or code the interface to the API on your own.
Step 2. Generate a user in Cognito for the backend system to use.
Step 3. Use the cognito user to obtain access tokens
Step 4. Use the access tokens to access the webservice in API
gateway.
Suggested solution
Create a second version of your API as a wrapper or extension to your mobile API and use API Keys as described above. Why?
Can throttle access to the APIs
A different version means you can extend it and add additional functionality specific to workflow
Easiest to implement as there is no key exchange, such updates to
the request header.
EDIT: My suggestion of solution 2 is incorrect. AWS Documentation says the following To include API methods in a usage plan, you must configure individual API methods to require an API key. For user authentication and authorization, don't use API keys. Use an IAM role, a Lambda authorizer, or an Amazon Cognito user pool.
AWS Also says the following is available for controlled access
Resource policies let you create resource-based policies to allow or deny access to your APIs and methods from specified source IP
addresses or VPC endpoints.
Standard AWS IAM roles and policies offer flexible and robust access controls that can be applied to an entire API or individual
methods.
Cross-origin resource sharing (CORS) lets you control how your API responds to cross-domain resource requests.
Lambda authorizers are Lambda functions that control access to your API methods using bearer token authentication as well as
information described by headers, paths, query strings, stage
variables, or context variables request parameters.
Amazon Cognito user pools let you create customizable authentication and authorization solutions.
Client-side SSL certificates can be used to verify that HTTP requests to your backend system are from API Gateway.
Usage plans let you provide API keys to your customers — and then track and limit usage of your API stages and methods for each API
key.
Not all the approaches above are intended for authorisation, for example CORS actually protects the user from cross site scripting, and as seen API Keys are only for usage plans. Resource policies just further secure the API by limiting access to IP Addresses, thus your only options really are IAM Roles as described in option 1, and federated users as described in option 3 or your own custom lambda authorize, if you are using Lambda, or your own authorizer if you are using something other than lambda wrapped with API Gateway.
I guess it will be service to service or (Server to Server) communication, for this terminology used is Oauth Standard is client_credentials grant type.
Please refer the documentation for getting token
Once the token is acquired, you need to pass this token either Authorization or API Gateway Custom Header for AWS Cognito.
You can use API Tokens alone for authorization (unless this has been removed recently)
I have used them on multiple applications.
This is not recommended for Authentication -- but it is application specific if they are sufficient for authorization
They have been supplemented by more secure methods at the expense of significant complication for both client and server.
API Tokens have the advantage of ease of use for issuer, client and server as they do not require complex signing or protocols -- however they are not as fundamentally secure as they may be reused and generally do not expire as quickly. Otherwise they are equivalent to bearer tokens.
Security is very context dependant -- consider these question:
what exactly are you protecting against (providing security for) ? What is the risk and cost of a security breach ? What is the cost/effort to implement and use it?
Many security 'holes' are not in the authentication protocol handling itself but rather in how data is managed 'outside the box' -- No security is perfect, meaning aiming for perfect security has unbounded cost with decreasing effectiveness. Generally, it is recommended to balance the risk and cost of potential loss vs cost to implement and maintain.
You can have a 'highly secure' API but also have a high risk of breach and data loss due to handling before and after passing through the protected gateway. There are many reasonable cases where instead of focusing on securing the 'front door' with bank vaults and armoured trucks, instead securing the data handling such that no data that is a significant security risk passes through the front door.
AWS Provides a range of technical features -- but it is ultimately up to each customer to implement them appropriate for their use. API Keys do have a range of appropriate use cases, particularly in server-to-server communications, especially where personal identity (and PI data) is not involved, or where the API involves mainly services instead of data (e.g say a image thumbnail API that stores no state and provides no access to data). When backed by use of HTTPS/SSL and possibly other security factors such as account passphrases, IP range whitelists, and a general policy of least-access.
Don't underestimate the "Sticky Note" factor. If you make secure access too painful to your users they will find a way to make it less painful, but less secure then simpler measures which they would not have had an incentive to circumvent.