{"id":23859216,"url":"https://github.com/openconext/openconext-attribute-aggregation","last_synced_at":"2025-09-08T07:30:47.654Z","repository":{"id":3057074,"uuid":"48314853","full_name":"OpenConext/OpenConext-attribute-aggregation","owner":"OpenConext","description":"OpenConext attribute aggregation","archived":false,"fork":false,"pushed_at":"2025-08-25T06:52:53.000Z","size":4323,"stargazers_count":1,"open_issues_count":1,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-08-25T09:26:14.498Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenConext.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-12-20T09:50:22.000Z","updated_at":"2025-08-25T06:52:57.000Z","dependencies_parsed_at":"2024-05-03T18:30:48.227Z","dependency_job_id":"262b73b9-5970-4ad9-a09c-b8496a8eed71","html_url":"https://github.com/OpenConext/OpenConext-attribute-aggregation","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/OpenConext/OpenConext-attribute-aggregation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenConext%2FOpenConext-attribute-aggregation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenConext%2FOpenConext-attribute-aggregation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenConext%2FOpenConext-attribute-aggregation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenConext%2FOpenConext-attribute-aggregation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenConext","download_url":"https://codeload.github.com/OpenConext/OpenConext-attribute-aggregation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenConext%2FOpenConext-attribute-aggregation/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274152117,"owners_count":25231285,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-08T02:00:09.813Z","response_time":121,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-03T03:32:57.161Z","updated_at":"2025-09-08T07:30:47.643Z","avatar_url":"https://github.com/OpenConext.png","language":"Java","readme":"# OpenConext-attribute-aggregation\n\n[![Build Status](https://travis-ci.org/OpenConext/OpenConext-attribute-aggregation.svg)](https://travis-ci.org/OpenConext/OpenConext-attribute-aggregation)\n[![codecov.io](https://codecov.io/github/OpenConext/OpenConext-attribute-aggregation/coverage.svg)](https://codecov.io/github/OpenConext/OpenConext-attribute-aggregation)\n\nOpenConext Attribute Aggregation\n\n## [Getting started](#getting-started)\n\n### [System Requirements](#system-requirements)\n\n- Java 21\n- Maven 3\n- MySQL 5.5\n- npm\n- node 7.10.0 (use for example nvm to manage it - latest version of node does not work)\n\nIf you have yarn installed, it will be used in the build by 3rd party libs. Ensure you are on version 1.1.0, otherwise\nthe sass node will break.\n\n### [Create database](#create-database)\n\nConnect to your local mysql database: `mysql -uroot`\n\nExecute the following:\n\n```sql\nCREATE DATABASE aaserver;\ngrant all on aaserver.* to 'root'@'localhost';\n```\n\n## [Building and running](#building-and-running)\n\n### [The server](#server)\n\nThis project uses Spring Boot and Maven. To run locally, type:\n\n`cd aa`\n\n`mvn spring-boot:run -Drun.jvmArguments=\"-Dspring.profiles.active=dev\"`\n\nWhen developing, it's convenient to just execute the applications main-method, which is in [Application](aa-server/src/main/java/aa/Application.java). Don't forget\nto set the active profile to dev.\n\n## [Miscellaneous](#miscellaneous)\n\n### [Testing](#testing)\n\nWhen manually testing the aggregations in the Playground you have to provide input attributes for retrieving values from the attribute authorities.\n\n* The attribute `urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified` with the value `urn:collab:person:example.com:admin` returns groups / isMemberOfs from VOOT\n* The attribute `urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified` with the value `urn:collab:person:surfnet.nl:henny` returns SAB roles\n* The attribute `urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified` with value `urn:collab:person:example.com:admin` returns a valid ORCID.\n\n### [cUrl](#curl)\n\nTo mimic the behaviour of attribute aggregation for an internal client - e.g. EngineBlock - we need to post form data:\n\n```bash\ncurl -X POST -H \"Content-Type: application/json\" --data-binary @./aa-server/src/test/resources/json/eb/request.json -u eb:secret https://aa.test2.surfconext.nl/aa/api/internal/attribute/aggregation\n```\n\nif you want to test all of the above curl commands against your locally running AttributeAggregation application then replace `https://aa.test2.surfconext.nl` with `http://localhost:8080`.\n\nThere is also an API for trusted clients to obtain account information based on the urn of the person:\n\n```bash\ncurl -u eb:secret https://aa.test2.surfconext.nl/aa/api/internal/accounts/urn:collab:person:example.com:admin\n```\n\nAnd the API offers a end-point to delete accounts:\n\n```bash\ncurl -u eb:secret -X \"DELETE\" \"https://aa.test2.surfconext.nl/aa/api/internal/disconnect/${account_id}\"\n```\n\nWhich will return Json `{\"status\": \"OK\"}` on success.\n\n### [Orcid](#orcid)\n\nYou can locally test the account linking with ORCID. You will need a valid orcid client id and secret. Copy \u0026 paste\nthe application.yml to application.local.yml and fill in the properties `orcid.client_id` and `orcid.secret`. Then use\nthis condiguration to start the server application:\n\n`mvn spring-boot:run -Drun.jvmArguments=\"-Dspring.profiles.active=dev\" -Dspring.config.name=application.dev`\n\nIf you go to the [connected page](http://localhost:8080/aa/api/client/information.html?redirectUrl=https://www.google.com) you\ncan link the dummy institutional user provided by the `MockShibbolethFilter` with an ORCID account.\n\nIf you don't specify a redirectUrl, then you will be redirected to the [information page](http://localhost:8080/aa/api/client/connected.html).\n\n### [New Attribute Authority](#new-attribute-authority)\n\nNew Attribute Authorities first must be added and configured in `attributeAuthoritiesProductionTemplate.yml`. Then add the new authority implementation to `AttributeAggregatorConfiguration#attributeAggregatorById`.\n\nTo actually use the new authority in the test/acc/prod environment it also needs to be configured in OpenConext-deploy [attributeAuthorities.yml.j2](https://github.com/OpenConext/OpenConext-deploy/blob/master/roles/attribute-aggregation-server/templates/attributeAuthorities.yml.j2).\n\n#### REST attribute aggregator\nThis reusable aggregator can be used for retrieving data from a REST endpoint and supports various options for configuring a HTTP request to that endpoint e.g. an API key.\nUsing this type does not require adding an authority implementation.\n\nNew entries are added in attributeAuthorities.yml.\n\nBelow is an example of the full configuration with explanations for the options:\n\n    - {\n        id: \"\u003cid\u003e\",\n        description: \"\u003cdescription\u003e\",\n        endpoint: \"\u003cendpoint\u003e\",\n        type: \"rest\",\n        // Username for basic authentication\n        user: \"\",\n        // Password for basic authentication\n        password: \"\",\n        // Headers to add in the HTTP request\n        headers: [\n            {\n              \"key\": \"\u003ckey\u003e\",\n              \"value\": \"\u003cvalue\u003e\",\n            }\n        ],\n        // Path parameters to use in the value for 'endpoint'\n        // Wildcards can be added with %s e.g. https://endpoint/%s/subpath/%s...\n        // The index below will correspond to the order in which the wildcards are replaced\n        // sourceAttribute refers to the attribute received from EngineBlock to use as the substitute\n        pathParams: [\n        {\n            \"index\": 0,\n            \"sourceAttribute\": \"urn:mace:terena.org:attribute-def:schacHomeOrganization\"\n        },\n        {\n            \"index\": 1,\n            \"sourceAttribute\": \"urn:mace:dir:attribute-def:uid\"\n        }\n        ],\n        // Options are 'GET', 'POST', 'PUT', 'DELETE', default is 'GET'\n        requestMethod: 'GET',\n        // Request parameters to use in the HTTP request, will be appended as ?name=value\u0026...\n        // sourceAttribute refers to the attribute received from EngineBlock to use as the substitute\n        requestParams: [\n            {\n                \"name\": \"\u003cname\u003e\",\n                \"sourceAttribute\": \"urn:mace:terena.org:attribute-def:schacHomeOrganization\"\n            }\n        ],\n        // Optional: specify node from API response for which to apply mapping for, by default the root node is used.\n        // Nesting is possible using dot notation e.g field.nestedField1[0].nestedField2 etc. Any paths navigations\n        // are possible from GPath\n        rootListName: \"\u003cnode name\u003e\",\n        // Mapping to apply to the response received from the HTTP request\n        // responseKey corresponds to the field in the response object of which to retrieve the value\n        // targetAttribute corresponds to the attribute to send the value as in the result of aggregation\n        mappings: [\n        {\n            \"responseKey\": \"myResponseKey\",\n            \"targetAttribute\": \"myTargetAttribute\"\n            // Optional: filter to search for specific node relative to the node used as root \n            // (after applying rootListName if present). Useful in case of searching for value \n            // where other field equals another value. \n            \"filter\": {\n                \"key\": \"\u003ckey\u003e\",\n                \"value\": \"\u003cvalue\u003e\"\n            }\n        }\n        ],\n        timeOut: 15000,\n        attributes: [],\n        requiredInputAttributes: [\n            {\n                name: \"urn:mace:terena.org:attribute-def:schacHomeOrganization\",\n            }\n        ],\n        validationRegExp: \"[a-zA-Z0-9]*\",\n        // Optional: specify caching which will be used in case an error occurs when retrieving data.\n        // Cache endpoint is configured separately but should return the same response structure as the primary endpoint.\n        cache: {\n            enabled: true,\n            endpoint: \"\u003cendpoint\u003e\",\n            headers: [\n                {\n                  \"key\": \"\u003ckey\u003e\",\n                  \"value\": \"\u003cvalue\u003e\",\n                }\n            ],\n            // Specify path to relevant record. Caution: if an entire list is retrieved then it is advised to \n            // define a filter to the relevant record e.g. findAll{record-\u003erecord.%s == \\\"%s\\\"}[0]. In this example\n            // attributes are used from the 'filters' section so that it is possible to filter by properties. Filters\n            // are optional. Path navigations and filter are possible from GPath\n            rootListName: \"\u003cnode name\u003e\", \n            filters: {\n                index: 0,\n                key: \"\u003ckey\u003e\",\n                sourceAttribute: \"\u003cattribute name\u003e\"\n            },\n            requestMethod: 'GET',\n            // Specify frequency at which data is retrieved from the cache endpoint\n            refreshCron: \"* * * * * *\"\n        }\n    }\n\n### [Configuration and deployment](#configuration-and-deployment)\n\nOn its classpath, the application has an [application.yml](aa-server/src/main/resources/application.yml) file that\ncontains configuration defaults that are convenient when developing.\n\nWhen the application actually gets deployed to a meaningful platform, it is pre-provisioned with ansible and the application.yml depends on\nenvironment specific properties in the group_vars. See the project OpenConext-deploy and the role aa for more information.\n\nFor details, see the [Spring Boot manual](http://docs.spring.io/spring-boot/docs/1.2.1.RELEASE/reference/htmlsingle/).\n\nWhen you want to run Attribute-Aggregator in a non-OpenConext environment you can use the [aa](aa-server/scripts/aa) script to stop / restart and start the application.\n\n### [LifeCycle Deprovisioning](#life-cycle-deprovisioning)\n\nThere is a LifeCycle API to deprovision users. The preview endpoint:\n```\ncurl -u life:secret http://localhost:8080/aa/api/deprovision/saml2_user.com | jq\n```\nAnd the actual `Deprovisioning` of the user:\n```\ncurl -X DELETE -u life:secret http://localhost:8080/deprovision/aa/api/saml2_user.com | jq\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenconext%2Fopenconext-attribute-aggregation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenconext%2Fopenconext-attribute-aggregation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenconext%2Fopenconext-attribute-aggregation/lists"}