Giter VIP home page Giter VIP logo

aws-scim-proxy's Introduction

AWS SCIM Proxy

The ForgeRock SCIM connector doesn't work, nor is it compliant with the SCIM requirements for AWS SSO. This proxy which uses API Gateway V2 and Lambda modifies the payload, so the schema meets AWS requirements.

Install

Clone the repository Run the command yarn install

Environment Variables

This project consumes a couple of environment variables for deployment and runtime. We recommended using direnv to manage these.

export PROXY_URL=https://scim.<AWS_REGION>.amazonaws.com
export AWS_TENANT_ID=<AWS TENANT UUID>

The PROXY_URL is the AWS host for the SCIM endpoint. You will need to change the region to fit your needs.

The AWS_TENANT_ID is the first path parameter for your unique SCIM endpoint. This will prevent all unknown requests from sent to the proxy.

Deploy

Serverless Framework is used to deploy the project to AWS. To run Serverless, run the command `yarn sls deploy -v

Both of the environment variables can be passed by the command by using --proxy-url and --aws-tenant-id.

Logging

There is no logging by default. By adding the environment variable TRACE_LOGGING to the lambda serverless configuration or through the AWS console and setting this to true, this will enable logging of the payloads going through the proxy and the payloads that the proxy generates.

TRACE_LOGGING=true yarn serverless deploy

โš ๏ธ PII may be contain in the payloads and by enabling logging, the payloads of all requests will be dumped to CloudWatch.

Data Transformation

Transforming data is based on methods. GET, POST and DELETE methods are passed through the proxy without modification. PUT and PATCH methods, their payloads are modified.

PUT requests

The ForgeRock SCIM connector has all the fields for an object in the root of the request body. From our testing, the ForgeRock SCIM connector does not use the PUT method to create a resource, only updating. See MDN HTTP PUT method reference for a further explanation of the PUT method.

An expected PUT payload from the ForgeRock SCIM connector would look like the following:

{
  "id": "some-id",
  "schemas": ["some-schema"],
  "userName": "bjensen",
  "displayName": "Babs Jensen",
  "active": true,
  "emails": [
    { "value": "[email protected]", "primary": true, "type": "work" }
  ]
}

The proxy will transform this into a PATCH request. It constructs each key-value pair (other than id and schemas) into a patch replace operation. The expected output from the proxy would be:

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    { "op": "replace", "path": "userName", "value": "bjensen" },
    { "op": "replace", "path": "displayName", "value": "Babs Jensen" },
    { "op": "replace", "path": "active", "value": true },
    {
      "op": "replace",
      "path": "emails",
      "value": [
        { "value": "[email protected]", "primary": true, "type": "work" },
        { "value": "[email protected]", "primary": false, "type": "personal" }
      ]
    }
  ]
}

Patch requests

The ForgeRock SCIM connector has the entire object inside the value field within an operation. The AWS SSO SCIM endpoint wants a singular value per operation with a path that is key to the value. The ForgeRock SCIM connector operation is a replace which the proxy respects.

An expected PATCH payload from the ForgeRock SCIM connector would look like the following:

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    {
      "op": "replace",
      "value": {
        "id": "some-id",
        "userName": "bjensen",
        "displayName": "Babs Jensen",
        "active": true,
        "emails": [
          { "value": "[email protected]", "primary": true, "type": "work" }
        ]
      }
    }
  ]
}

The proxy will transform the singular operation into a multi-operation payload. It constructs each key-value pair (other than id) into its own replace operation. The expected output from the proxy would be:

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    { "op": "replace", "path": "userName", "value": "bjensen" },
    { "op": "replace", "path": "displayName", "value": "Babs Jensen" },
    { "op": "replace", "path": "active", "value": true },
    {
      "op": "replace",
      "path": "emails",
      "value": [
        { "value": "[email protected]", "primary": true, "type": "work" }
      ]
    }
  ]
}

Member operations in PATCH payloads

The ForgeRock SCIM connector doesn't respect the AWS SSO SCIM endpoint's requirements for member management within a group. The member's key-value pair is located in the root object with everything else in the PUT request. See the example above. The member's value is an array of string ids.

We have tested the replace operation with members which AWS offers on their endpoint. We were unable to get this working. See the documentation for this operation (Supported API Operations -> PatchGroup -> Member operations examples -> Replace members in a group). Knowing that, the proxy uses create and remove operations for members instead.

The expected payload from the ForgeRock SCIM connector would look like the following:

{
  "id": "some-id",
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    {
      "op": "replace",
      "value": [
        { "value": "4be0643f-1d98-573b-97cd-ca98a65347dd" },
        { "value": "86e3aed3-1553-5d23-8d61-2286215e65f1" },
        { "value": "20ca53af-d04c-58a2-a8b3-d02b9e414e80" }
      ]
    }
  ]
}

As the proxy does not know the difference between the ForgeRock group memberships and the AWS SSO group memberships, it will create this in a stateless form.

  1. It will fetch all users on the AWS SSO through the SCIM connector. This is because the AWS SSO SCIM endpoint doesn't list member ids when fetching the group from the endpoint. This is listed on the AWS SSO SCIM endpoint documentation (Supported API Operations -> ListGroups -> Not supported).
  2. Using the AWS SSO SCIM groups endpoint, the proxy will use a query to fetch the group relationship between the group and user. This returns an array of memberships. As the query expects either one or zero relationships, this is what is uses to understand if that user is in a relationship on the AWS SSO side.
  3. With the knowledge from the ForgeRock SCIM connector about which members are to be with this group and the information derived from the AWS SSO SCIM endpoint, the proxy can create a diff. Members to be added, members who are staying and members to be removed.
  4. Two operations will be created an add and remove operation. These will facilitate the member operations. The operations are added to the overall transformation of the PATCH request to the PATCH operations request.

The expected output from the proxy would be:

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    {
      "op": "add",
      "path": "members",
      "value": [
        { "value": "4be0643f-1d98-573b-97cd-ca98a65347dd" },
        { "value": "86e3aed3-1553-5d23-8d61-2286215e65f1" }
      ]
    },
    {
      "op": "remove",
      "path": "members",
      "value": [{ "value": "20ca53af-d04c-58a2-a8b3-d02b9e414e80" }]
    }
  ]
}

From the two example payloads, this is what was expected. This would be the current state of the group from ForgeRock and AWS SSO.

ForgeRock Group AWS SSO Group
4be0643f-1d98-573b-97cd-ca98a65347dd
86e3aed3-1553-5d23-8d61-2286215e65f1
6eabff02-c968-5cbc-bc7f-3b672928a761 6eabff02-c968-5cbc-bc7f-3b672928a761
20ca53af-d04c-58a2-a8b3-d02b9e414e80

ForgeRock SCIM connector sends a request that the users it listed are to be the only users in the group. We can see from the above table that two of the users are not currently in the group and need to be added to the group. One of the users is already in the group and a final user that needs to be removed from the group.

Notes on proxy

Response statues

The proxy will forward all status codes to the downstream (ForgeRock) except in the following cases.

  1. PUT requests expect a 200 response code back. As the proxy is transforming these to a PATCH request, the AWS SSO SCIM endpoint returns a 204. A body will be constructed with the id of the resource, and the status code will be changed to 200 before sending the request downstream.

429 status from AWS SSO SCIM endpoint

If there are many requests sent to the AWS endpoint, it can return a 429 Too Many Request status. As the proxy is stateless, the current request will be cancelled, but future requests will be still proxied, resulting in further errors. The AWS SSO SCIM endpoint will include the header Retry-After which will not be respected.

Header stripping

The content-length header will be stripped as it will be recalculated when the upstream request is sent.

The host header will be stripped and replaced with the AWS SSO SCIM endpoint hostname.

Maximum Users

The AWS SSO SCIM Endpoint has a maximum list size of 50 users and 50 groups. Due to the transformation that takes place, it needs to fetch all the users and create a diff between ForgeRock and AWS SSO. The current maximum sync capabilities is 50 users. Groups do not suffer this issue as the proxy doesn't need to know about the groups. The AWS API for Identity Store has a different issue also preventing the use of that.

This limitation could have unforeseen issues with ForgeRock.

aws-scim-proxy's People

Contributors

dspasojevic avatar sammurphydev avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.