├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .mongo ├── mongo_init.sh └── replica.key ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ └── maven-wrapper.properties ├── LICENSE.txt ├── build.sh ├── config └── scim │ ├── data1 │ ├── pubStream.json │ ├── receiveStream.json │ └── test.prop │ └── schema │ ├── default-acis.json │ ├── default-resourceTypes.json │ ├── resourceTypes.json │ ├── scimCommonSchema.json │ ├── scimFixedSchema.json │ └── scimSchema.json ├── docker-compose-mongo-cluster.yml ├── docker-compose-signals.yml ├── docs ├── AccessControl.md ├── CNAME ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Configuration.md ├── DeveloperNotes.md ├── Intro-to-SCIM.md ├── OPA_AccessControl.md ├── README.md ├── SCIM_B-and-W_400x136.png ├── SCIM_B-and-W_792x270.jpg ├── Signals.md ├── github-logo-i2scim.png ├── i2scim-client-introduction.md └── i2scim-mongo-k8s.md ├── i2scim-client ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── independentid │ │ └── scim │ │ └── client │ │ ├── ResourceBuilder.java │ │ ├── ScimReqParams.java │ │ ├── i2scimClient.java │ │ └── i2scimResponse.java │ └── resources │ └── schema │ ├── resourceTypes.json │ ├── scimCommonSchema.json │ ├── scimFixedSchema.json │ └── scimSchema.json ├── i2scim-core ├── .mvn │ └── wrapper │ │ ├── .gitignore │ │ ├── MavenWrapperDownloader.java │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── independentid │ └── scim │ ├── backend │ ├── BackendException.java │ ├── BackendHandler.java │ ├── BackendProvider.java │ ├── CachedProviderSupplier.java │ ├── IIdentifierGenerator.java │ ├── IResourceModifier.java │ ├── IScimProvider.java │ └── package-info.java │ ├── core │ ├── AuditLog.java │ ├── ConfigMgr.java │ ├── FifoCache.java │ ├── InjectionManager.java │ ├── PoolManager.java │ └── err │ │ ├── BadFilterException.java │ │ ├── ConflictException.java │ │ ├── DuplicateTxnException.java │ │ ├── ForbiddenException.java │ │ ├── InternalException.java │ │ ├── InvalidSyntaxException.java │ │ ├── InvalidValueException.java │ │ ├── MethodNotAllowedException.java │ │ ├── NoTargetException.java │ │ ├── NotFoundException.java │ │ ├── NotImplementedException.java │ │ ├── NullValueException.java │ │ ├── PreconditionFailException.java │ │ ├── ScimException.java │ │ ├── TooLargeException.java │ │ ├── TooManyException.java │ │ └── UnauthorizedException.java │ ├── events │ ├── EventManager.java │ ├── IEventHandler.java │ └── PublishOperation.java │ ├── op │ ├── BulkOps.java │ ├── CreateOp.java │ ├── DeleteOp.java │ ├── GetOp.java │ ├── HeadOp.java │ ├── IBulkIdResolver.java │ ├── IBulkIdTarget.java │ ├── IBulkOp.java │ ├── OpStat.java │ ├── Operation.java │ ├── PatchOp.java │ ├── PutOp.java │ └── SearchOp.java │ ├── plugin │ ├── IScimPlugin.java │ └── PluginHandler.java │ ├── protocol │ ├── AttributeFilter.java │ ├── BulkResponse.java │ ├── ConfigResponse.java │ ├── Filter.java │ ├── JsonPatchBuilder.java │ ├── JsonPatchOp.java │ ├── JsonPatchRequest.java │ ├── JsonPath.java │ ├── ListResponse.java │ ├── LogicFilter.java │ ├── PrecedenceFilter.java │ ├── RequestCtx.java │ ├── ResourceResponse.java │ ├── ScimParams.java │ ├── ScimResponse.java │ └── ValuePathFilter.java │ ├── pwd │ ├── PasswordToken.java │ └── PasswordValue.java │ ├── resource │ ├── BinaryValue.java │ ├── BooleanValue.java │ ├── ComplexValue.java │ ├── DateValue.java │ ├── DecimalValue.java │ ├── ExtensionValues.java │ ├── GroupsValue.java │ ├── IntegerValue.java │ ├── Meta.java │ ├── MultiValue.java │ ├── PersistStateResource.java │ ├── ReferenceValue.java │ ├── ScimResource.java │ ├── StringValue.java │ ├── TransactionRecord.java │ ├── Value.java │ ├── ValueUtil.java │ └── package-info.java │ ├── schema │ ├── Attribute.java │ ├── IVirtualValue.java │ ├── MetaAttribute.java │ ├── ResourceType.java │ ├── Schema.java │ ├── SchemaException.java │ ├── SchemaExtension.java │ ├── SchemaManager.java │ └── SystemSchemas.java │ ├── security │ ├── AccessControl.java │ ├── AccessManager.java │ ├── AccessPlugin.java │ ├── AciSet.java │ ├── PasswordHandlerPlugin.java │ ├── ScimAuthMechanism.java │ ├── ScimAuthorizationController.java │ ├── ScimBasicIdentityProvider.java │ └── ScimRoleAugmentor.java │ └── serializer │ ├── JsonUtil.java │ ├── ScimResponseSerializer.java │ └── ScimSerializer.java ├── i2scim-prov-memory ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── independentid │ └── scim │ └── backend │ └── memory │ ├── IndexResourceType.java │ ├── MemoryIdGenerator.java │ ├── MemoryProvider.java │ └── ValResMap.java ├── i2scim-prov-mongo ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── independentid │ └── scim │ └── backend │ └── mongo │ ├── MongoDateConverter.java │ ├── MongoFilterMapper.java │ ├── MongoIdGenerator.java │ ├── MongoMapUtil.java │ ├── MongoProvider.java │ ├── MongoScimResource.java │ └── package-info.java ├── i2scim-server ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── independentid │ └── scim │ ├── filter │ ├── OpaSecurityFilter.java │ └── ScimSecurityFilter.java │ └── server │ ├── ScimV2Servlet.java │ ├── i2scimHealthCheck.java │ └── i2scimLivenessCheck.java ├── i2scim-signals ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── independentid │ │ │ ├── auth │ │ │ └── SsfAuthorizationToken.java │ │ │ ├── set │ │ │ ├── SecurityEventToken.java │ │ │ └── SubjectIdentifier.java │ │ │ └── signals │ │ │ ├── EventTypes.java │ │ │ ├── PollStream.java │ │ │ ├── PushStream.java │ │ │ ├── SignalsEventHandler.java │ │ │ ├── SignalsEventMapper.java │ │ │ ├── SignalsEventReceiver.java │ │ │ ├── SsfHandler.java │ │ │ ├── StreamConfigProps.java │ │ │ └── StreamModels.java │ └── resources │ │ ├── application-testing.properties │ │ ├── application.properties │ │ └── schema │ │ ├── acis.json │ │ ├── resourceTypes.json │ │ ├── scimCommonSchema.json │ │ ├── scimFixedSchema.json │ │ └── scimSchema.json │ └── test │ ├── java │ └── com │ │ └── independentid │ │ └── scim │ │ └── test │ │ ├── events │ │ ├── MockSignalsServer.java │ │ ├── SignalsEventHandlerTest.java │ │ ├── SignalsEventMapperTest.java │ │ ├── SignalsEventTestProfile.java │ │ └── TestUtils.java │ │ ├── set │ │ ├── SetTest.java │ │ └── SignalsSetTestProfile.java │ │ └── ssf │ │ ├── SignalsSsfTestProfile.java │ │ └── SsfClientTest.java │ └── resources │ ├── certs │ ├── jwks-certs-copy.json │ └── jwks-certs.json │ ├── data │ ├── TestUser-bjensen.json │ ├── TestUser-jsmith.json │ ├── TestUsers.json │ ├── issuer.pem │ ├── jwk-sign.json │ ├── pubStream.json │ ├── receiveStream.json │ ├── user-1000.json │ ├── user-10pretty.json │ └── user-5000.json │ ├── schema │ ├── aciSecurityTest.json │ ├── acis.json │ ├── scimCommonSchema.json │ ├── scimFixedSchema.json │ ├── scimSchema.json │ ├── scimSchemaTest.json │ └── scimTestSchema.json │ └── scim │ └── ReadMe.txt ├── i2scim-tests ├── opa │ ├── .run │ │ └── test i2scim.run.xml │ ├── opa_start.sh │ └── policy │ │ ├── data.json │ │ └── i2scim-authz.rego ├── pom.xml ├── scimdata │ └── resourceTypes.json └── src │ ├── main │ └── resources │ │ ├── META-INF │ │ ├── beans.xml │ │ └── resources │ │ │ └── index.html │ │ ├── application.properties │ │ ├── certs │ │ └── jwks-certs.json │ │ ├── log4j.properties │ │ ├── resources-config.json │ │ └── schema │ │ ├── acis.json │ │ ├── resourceTypes.json │ │ ├── scimCommonSchema.json │ │ ├── scimFixedSchema.json │ │ └── scimSchema.json │ └── test │ ├── java │ └── com │ │ └── independentid │ │ └── scim │ │ └── test │ │ ├── auth │ │ ├── AccessMgrTest.java │ │ ├── ScimAuthTest.java │ │ ├── ScimAuthTestProfile.java │ │ └── ScimAuthZCRUDTest.java │ │ ├── client │ │ └── i2ClientTest.java │ │ ├── devops │ │ ├── ScimDevOpsTestProfile.java │ │ └── ScimHealthTest.java │ │ ├── http │ │ ├── ScimAttributeQualTest.java │ │ ├── ScimConfigEndpointTest.java │ │ ├── ScimConstraintsTest.java │ │ ├── ScimGroupCRUDTest.java │ │ ├── ScimHttpTestProfile.java │ │ ├── ScimLoadSampleTest.java │ │ ├── ScimLoadSampleTestParallel.java │ │ ├── ScimPatchTest.java │ │ └── ScimUserCRUDTest.java │ │ ├── memory │ │ ├── MemoryConfigTest.java │ │ ├── MemoryFilterMapTest.java │ │ ├── MemoryIndexTest.java │ │ ├── MemoryProviderTest.java │ │ └── ScimMemoryTestProfile.java │ │ ├── misc │ │ ├── CycleTestKeys.java │ │ ├── JwtTokenTest.java │ │ └── TestUtils.java │ │ ├── mongo │ │ ├── MongoConfigTest.java │ │ ├── MongoFilterMapTest.java │ │ ├── MongoProviderTest.java │ │ ├── MongoTests.md │ │ └── ScimMongoTestProfile.java │ │ ├── opa │ │ ├── OpaTest.java │ │ └── OpaTestProfile.java │ │ ├── password │ │ └── PasswordTest.java │ │ └── sub │ │ ├── BasicResourceSchemaConfigTest.java │ │ ├── FilterParserTest.java │ │ ├── JacksonTest.java │ │ ├── ReferenceValueTest.java │ │ ├── SchemaManagerTest.java │ │ ├── ScimResourceTest.java │ │ ├── ScimSubComponentTestProfile.java │ │ └── ScimValuePathMatchTest.java │ └── resources │ ├── certs │ └── jwks-certs.json │ ├── data │ ├── user-1000.json │ ├── user-10pretty.json │ └── user-5000.json │ └── schema │ ├── TestUser-bjensen.json │ ├── TestUser-jsmith.json │ ├── TestUsers.json │ ├── aciSecurityTest.json │ ├── acis.json │ ├── scimCommonSchema.json │ ├── scimFixedSchema.json │ ├── scimSchema.json │ ├── scimSchemaTest.json │ └── scimTestSchema.json ├── i2scim-universal ├── 1-i2scim-memory-configs.yaml ├── 2-i2scim-gke-memory-pvset.yaml ├── 2-i2scim-memory-pvset.yaml ├── 3-i2scim-config-schema.yaml ├── 4-i2scim-memory-deploy.yml ├── build.sh ├── deploy-instructions.md ├── pom.xml ├── scim │ └── ReadMe.txt └── src │ └── main │ ├── docker │ ├── Dockerfile.jvm │ ├── Dockerfile.legacy-jar │ ├── Dockerfile.native │ └── Dockerfile.native-micro │ └── resources │ ├── META-INF │ ├── beans.xml │ └── resources │ │ └── index.html │ ├── application.properties │ ├── log4j.properties │ ├── resources-config.json │ └── schema │ ├── acis.json │ ├── resourceTypes.json │ ├── scimCommonSchema.json │ ├── scimFixedSchema.json │ └── scimSchema.json ├── mvnw ├── mvnw.cmd ├── opa ├── opa_start.sh └── policy │ ├── data.json │ └── i2scim-authz.rego ├── pkg-i2scim-prov-memory ├── 1-i2scim-memory-configs.yaml ├── 2-i2scim-gke-memory-pvset.yaml ├── 2-i2scim-memory-pvset.yaml ├── 3-i2scim-config-schema.yaml ├── 4-i2scim-memory-deploy.yml ├── README.md ├── deploy-instructions.md ├── pom.xml ├── scim │ └── ReadMe.txt └── src │ └── main │ ├── docker │ ├── Dockerfile.jvm │ ├── Dockerfile.legacy-jar │ ├── Dockerfile.native │ └── Dockerfile.native-micro │ └── resources │ ├── META-INF │ ├── beans.xml │ └── resources │ │ └── index.html │ ├── application.properties │ ├── log4j.properties │ ├── resources-config.json │ └── schema │ ├── acis.json │ ├── resourceTypes.json │ ├── scimCommonSchema.json │ ├── scimFixedSchema.json │ └── scimSchema.json ├── pkg-i2scim-prov-mongodb ├── 1-i2scim-mongo-configs.yaml ├── 2-i2scim-gke-mongo-pvset.yaml ├── 2-i2scim-mongo-pvset.yaml ├── 3-i2scim-config-schema.yaml ├── 4-i2scim-mongo-set.yml ├── README.md ├── dbmongo-test-service.yaml ├── pom.xml ├── scim │ └── ReadMe.txt └── src │ ├── main │ ├── docker │ │ ├── Dockerfile.jvm │ │ ├── Dockerfile.legacy-jar │ │ ├── Dockerfile.native │ │ └── Dockerfile.native-micro │ └── resources │ │ ├── META-INF │ │ ├── beans.xml │ │ └── resources │ │ │ └── index.html │ │ ├── application.properties │ │ ├── log4j.properties │ │ ├── resources-config.json │ │ └── schema │ │ ├── acis.json │ │ ├── default-resourceTypes.json │ │ ├── resourceTypes.json │ │ ├── scimCommonSchema.json │ │ ├── scimFixedSchema.json │ │ └── scimSchema.json │ └── test │ ├── java │ └── com │ │ └── independentid │ │ └── scim │ │ └── test │ │ ├── http │ │ ├── LoadScimClusterTest.java │ │ └── ScimClientProfile.java │ │ └── misc │ │ └── TestUtils.java │ └── resources │ ├── data │ ├── cluster-config.prop │ ├── user-1000.json │ ├── user-10pretty.json │ └── user-5000.json │ └── schema │ ├── resourceTypes.json │ ├── scimCommonSchema.json │ ├── scimFixedSchema.json │ └── scimSchema.json ├── pom.xml └── spec ├── oas └── scimv2-api.yaml └── schema ├── scim-bulkRequest.schema.json ├── scim-createResourceRequest.schema.json ├── scim-errorResponse.schema.json ├── scim-listResponse.schema.json ├── scim-patchRequest.schema.json ├── scim-resource.schema.json ├── scim-searchRequest.schema.json └── scim-serviceProviderConfigResponse.schema.json /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Describe your K8S deployment and provide example YAML if possible. 15 | 16 | Steps to reproduce the behavior: 17 | 1. Go to '...' 18 | 2. Click on '....' 19 | 3. Scroll down to '....' 20 | 4. See error 21 | 22 | **Expected behavior** 23 | A clear and concise description of what you expected to happen. If SCIM protocol related please provide example request, response, and expected response. 24 | 25 | **Screenshots** 26 | If applicable, add screenshots to help explain your problem. 27 | 28 | **Deployment (please complete the following information):** 29 | - K8S Environment: [e.g. AWS] 30 | - i2scim version: [e.g. 0.5.0-Alpha] 31 | - i2scim Provider: [e.g. Mongo] 32 | - Other details: [e.g. YAML] 33 | 34 | **SCIM Client Description:** 35 | - Device: [e.g. iPhone6] 36 | - OS: [e.g. iOS8.1] 37 | - Browser [e.g. stock browser, safari] 38 | - Version [e.g. 22] 39 | 40 | **Additional context** 41 | Add any other context about the problem here. 42 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Enhancement Type:** 11 | Is this to implement something that is part of or an extension to the SCIM standard? A provider to a new API or persistence provider? A new core feature (e.g. replication)? 12 | [e.g. Standard | Provider | Core | Event ] 13 | 14 | **Is your feature request related to a problem? Please describe.** 15 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 16 | 17 | **Describe the solution you'd like** 18 | A clear and concise description of what you want to happen. 19 | 20 | **Describe alternatives you've considered** 21 | A clear and concise description of any alternative solutions or features you've considered. 22 | 23 | **Additional context** 24 | Add any other context or screenshots about the feature request here. 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | **.versionsBackup 8 | 9 | ### STS ### 10 | .apt_generated 11 | .classpath 12 | .factorypath 13 | .project 14 | .settings 15 | .springBeans 16 | .sts4-cache 17 | 18 | ### IntelliJ IDEA ### 19 | .idea 20 | *.iws 21 | *.iml 22 | *.ipr 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | /.DS_Store 37 | /.gitignore 38 | /i2scim-tests/scimdata/ 39 | /opa/.run/ 40 | 41 | 42 | /i2scim-tests/logs/ 43 | -------------------------------------------------------------------------------- /.mongo/mongo_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "sleeping for 15 seconds" 3 | sleep 15 4 | 5 | echo mongo_init.sh time now: `date +"%T" ` 6 | mongosh -u root -p dockTest --host mongo1:30001 <... 24 | */ 25 | public class CachedProviderSupplier implements Supplier { 26 | private final Supplier supplier; 27 | private final ArrayList cache; 28 | 29 | public CachedProviderSupplier(Supplier supplier) { 30 | this.supplier = supplier; 31 | this.cache = new ArrayList<>(1); 32 | } 33 | 34 | public IScimProvider get() { 35 | if (cache.isEmpty()) { 36 | IScimProvider prov = supplier.get(); 37 | cache.add(prov); 38 | } 39 | return cache.get(0); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/backend/IIdentifierGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.backend; 18 | 19 | public interface IIdentifierGenerator { 20 | 21 | /** 22 | * Generates and obtains an identifier usable for objects within the persistence provider. This is most typically 23 | * used for generating transactionIds which will be ultimately stored in the providers "Trans" container. 24 | * @return A String value that can be used as an object identifier. 25 | */ 26 | String getNewIdentifier(); 27 | 28 | String getProviderClass(); 29 | } 30 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/backend/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This module provides the common provider interfaces that i2scim will call 17 | * to perform SCIM requests to a backend provider. 18 | */ 19 | /** 20 | * @author pjdhunt 21 | * 22 | */ 23 | package com.independentid.scim.backend; -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/AuditLog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core; 17 | 18 | import com.independentid.scim.op.Operation; 19 | import com.independentid.scim.protocol.ScimResponse; 20 | import jakarta.enterprise.context.ApplicationScoped; 21 | 22 | /** 23 | * @author pjdhunt 24 | * 25 | */ 26 | 27 | @ApplicationScoped 28 | public class AuditLog { 29 | 30 | public final static String PARAM_AUDIT_LOGFILE = "scim.audit.logfile"; 31 | public final static String DEFAULT_AUDIT_LOGFILE = "./audit.log"; 32 | 33 | //private BufferedOutputStream out; 34 | 35 | /** 36 | * 37 | */ 38 | public AuditLog() { 39 | 40 | } 41 | 42 | public void logEvent(Operation op, ScimResponse resp) { 43 | 44 | } 45 | 46 | public void shutdown() { 47 | 48 | } 49 | 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/FifoCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.core; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.concurrent.locks.Lock; 22 | import java.util.concurrent.locks.ReentrantLock; 23 | 24 | public class FifoCache { 25 | private final int size; 26 | private final List list; 27 | private final Lock lock; 28 | 29 | public FifoCache(int size) { 30 | this.size = size; 31 | list = new ArrayList<>(size); 32 | lock = new ReentrantLock(); 33 | } 34 | 35 | public void add(T item) { 36 | if (size ==0) 37 | return; // cache disabled 38 | lock.lock(); 39 | try { 40 | while (list.size() >= size) 41 | list.remove(0); 42 | list.add(item); 43 | } finally { 44 | lock.unlock(); 45 | } 46 | } 47 | 48 | public T get(int ind) { 49 | lock.lock(); 50 | try { 51 | return list.get(ind); 52 | } finally { 53 | lock.unlock(); 54 | } 55 | } 56 | 57 | public T next() { 58 | lock.lock(); 59 | try { 60 | return list.remove(0); 61 | } finally { 62 | lock.unlock(); 63 | } 64 | } 65 | 66 | public int size() { 67 | lock.lock(); 68 | try { 69 | return list.size(); 70 | } finally { 71 | lock.unlock(); 72 | } 73 | } 74 | 75 | public boolean isEmpty() { 76 | lock.lock(); 77 | try { 78 | return list.isEmpty(); 79 | } finally { 80 | lock.unlock(); 81 | } 82 | } 83 | 84 | public void clear() { 85 | lock.lock(); 86 | try { 87 | list.clear(); 88 | } finally { 89 | lock.unlock(); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/BadFilterException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.independentid.scim.protocol.ScimResponse; 19 | 20 | public class BadFilterException extends ScimException { 21 | 22 | public final static String SCIM_TYPE = ScimResponse.ERR_TYPE_FILTER; 23 | 24 | private static final long serialVersionUID = 1L; 25 | 26 | public BadFilterException() { 27 | this.scimType = SCIM_TYPE; 28 | this.status = 400; 29 | } 30 | 31 | public BadFilterException(String message) { 32 | super(message); 33 | this.scimType = SCIM_TYPE; 34 | this.status = 400; 35 | } 36 | 37 | public BadFilterException(String message, String scimType) { 38 | super(message, scimType); 39 | this.status = 400; 40 | 41 | } 42 | 43 | public BadFilterException(Throwable cause) { 44 | super(cause); 45 | this.scimType = SCIM_TYPE; 46 | this.status = 400; 47 | this.detail = cause.getLocalizedMessage(); 48 | } 49 | 50 | public BadFilterException(String message, Throwable cause) { 51 | super(message, cause); 52 | this.scimType = SCIM_TYPE; 53 | this.status = 400; 54 | this.detail = cause.getLocalizedMessage(); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/ConflictException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | 19 | public class ConflictException extends ScimException { 20 | 21 | /** 22 | * 23 | */ 24 | private static final long serialVersionUID = 1L; 25 | 26 | /** 27 | * ConflictException - Used to return HTTP Status 409. Caused by 28 | * an mis-match version (etag), or a conflict occurred for an 29 | * attribute that is defined as "unique". 30 | */ 31 | public ConflictException() { 32 | this.scimType = null; 33 | this.status = 409; 34 | } 35 | 36 | /** 37 | * ConflictException - Used to return HTTP Status 409. Caused by 38 | * an mis-match version (etag), or a conflict occurred for an 39 | * attribute that is defined as "unique". 40 | * @param message A string containing explanation text to be 41 | * returned in SCIM "detail" error message. 42 | */ 43 | public ConflictException(String message) { 44 | super(message); 45 | this.scimType = null; 46 | this.status = 409; 47 | } 48 | 49 | public ConflictException(Throwable cause) { 50 | super(cause); 51 | this.scimType = null; 52 | this.status = 409; 53 | this.detail = cause.getLocalizedMessage(); 54 | } 55 | 56 | public ConflictException(String message, Throwable cause) { 57 | super(message, cause); 58 | this.scimType = null; 59 | this.status = 409; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/DuplicateTxnException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.core.err; 18 | 19 | /** 20 | * Exception is thrown when a duplicate revision value is detected in meta.revisions. 21 | */ 22 | public class DuplicateTxnException extends ConflictException { 23 | 24 | public DuplicateTxnException(String message) { 25 | super(message); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/ForbiddenException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.independentid.scim.protocol.ScimResponse; 19 | 20 | /* 21 | * ForbiddenException is thrown when SCIM client attempts to perform an 22 | * operation that is not permitted based on the supplied authorization. 23 | * See Sec 3.12 of RFC7644. 24 | */ 25 | public class ForbiddenException extends ScimException { 26 | { status = ScimResponse.ST_FORBIDDEN; } 27 | /** 28 | * 29 | */ 30 | private static final long serialVersionUID = 1L; 31 | 32 | public ForbiddenException() { 33 | 34 | } 35 | 36 | public ForbiddenException(String message) { 37 | super(message); 38 | 39 | } 40 | 41 | public ForbiddenException(String message, String scimType) { 42 | super(message, scimType); 43 | } 44 | 45 | public ForbiddenException(Throwable cause) { 46 | super(cause); 47 | 48 | this.detail = cause.getLocalizedMessage(); 49 | } 50 | 51 | public ForbiddenException(String message, Throwable cause) { 52 | super(message, cause); 53 | this.detail = cause.getLocalizedMessage(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/InternalException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.independentid.scim.protocol.ScimResponse; 19 | 20 | public class InternalException extends ScimException { 21 | 22 | 23 | private static final long serialVersionUID = 1L; 24 | 25 | public InternalException() { 26 | this.status = ScimResponse.ST_INTERNAL; 27 | 28 | } 29 | 30 | public InternalException(String message) { 31 | super(message); 32 | this.status = ScimResponse.ST_INTERNAL; 33 | this.detail = message; 34 | 35 | } 36 | 37 | public InternalException(String message, String scimType) { 38 | super(message, scimType); 39 | this.status = ScimResponse.ST_INTERNAL; 40 | } 41 | 42 | public InternalException(Throwable cause) { 43 | super(cause); 44 | this.status = ScimResponse.ST_INTERNAL; 45 | this.detail = cause.getLocalizedMessage(); 46 | } 47 | 48 | public InternalException(String message, Throwable cause) { 49 | super(message, cause); 50 | this.status = ScimResponse.ST_INTERNAL; 51 | this.detail = cause.getLocalizedMessage(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/InvalidSyntaxException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.independentid.scim.protocol.ScimResponse; 19 | 20 | /** 21 | * @author pjdhunt 22 | * InvalidSyntaxException - The request body message structure was invalid or 23 | * did not conform to the request schema. 24 | */ 25 | public class InvalidSyntaxException extends ScimException { 26 | 27 | private static final long serialVersionUID = 1L; 28 | 29 | public final static String SCIM_TYPE = ScimResponse.ERR_TYPE_SYNTAX; 30 | 31 | /** 32 | * InvalidSyntaxException - The request body message structure was 33 | * invalid or did not conform to the request schema. 34 | */ 35 | public InvalidSyntaxException() { 36 | this.scimType = SCIM_TYPE; 37 | this.status = 400; 38 | } 39 | 40 | /** 41 | * InvalidSyntaxException - The request body message structure was 42 | * invalid or did not conform to the request schema. 43 | * @param message A description of the error to be returned in error detail 44 | */ 45 | public InvalidSyntaxException(String message) { 46 | super(message); 47 | this.scimType = SCIM_TYPE; 48 | this.status = 400; 49 | } 50 | 51 | public InvalidSyntaxException(Throwable cause) { 52 | super(cause); 53 | this.scimType = SCIM_TYPE; 54 | this.status = 400; 55 | this.detail = cause.getLocalizedMessage(); 56 | } 57 | 58 | public InvalidSyntaxException(String message, Throwable cause) { 59 | super(message, cause); 60 | this.scimType = SCIM_TYPE; 61 | this.status = 400; 62 | this.detail = cause.getLocalizedMessage(); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/InvalidValueException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.independentid.scim.protocol.ScimResponse; 19 | 20 | public class InvalidValueException extends ScimException { 21 | 22 | /** 23 | * 24 | */ 25 | private static final long serialVersionUID = 1L; 26 | public final static String SCIM_TYPE = ScimResponse.ERR_TYPE_BADVAL; 27 | 28 | public InvalidValueException() { 29 | this.scimType = SCIM_TYPE; 30 | this.status = 400; 31 | } 32 | 33 | public InvalidValueException(String message) { 34 | super(message); 35 | this.scimType = SCIM_TYPE; 36 | this.status = 400; 37 | } 38 | 39 | public InvalidValueException(Throwable cause) { 40 | super(cause); 41 | this.scimType = SCIM_TYPE; 42 | this.status = 400; 43 | this.detail = cause.getLocalizedMessage(); 44 | } 45 | 46 | public InvalidValueException(String message, Throwable cause) { 47 | super(message, cause); 48 | this.scimType = SCIM_TYPE; 49 | this.status = 400; 50 | this.detail = cause.getLocalizedMessage(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/MethodNotAllowedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.core.err; 18 | 19 | import jakarta.servlet.http.HttpServletResponse; 20 | 21 | /** 22 | * MethodNotAllowed when HTTP Method used against a resource where it is not appropriate. E.g. patch on a container (top level). 23 | */ 24 | public class MethodNotAllowedException extends ScimException { 25 | { status = HttpServletResponse.SC_METHOD_NOT_ALLOWED; } 26 | /** 27 | * 28 | */ 29 | private static final long serialVersionUID = 1L; 30 | 31 | public MethodNotAllowedException () { 32 | 33 | } 34 | 35 | public MethodNotAllowedException (String message) { 36 | super(message); 37 | 38 | } 39 | 40 | public MethodNotAllowedException (String message, String scimType) { 41 | super(message, scimType); 42 | } 43 | 44 | public MethodNotAllowedException (Throwable cause) { 45 | super(cause); 46 | 47 | this.detail = cause.getLocalizedMessage(); 48 | } 49 | 50 | public MethodNotAllowedException (String message, Throwable cause) { 51 | super(message, cause); 52 | this.detail = cause.getLocalizedMessage(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/NoTargetException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.independentid.scim.protocol.ScimResponse; 19 | 20 | public class NoTargetException extends ScimException { 21 | 22 | /** 23 | * 24 | */ 25 | private static final long serialVersionUID = 1L; 26 | 27 | public final static String SCIM_TYPE = ScimResponse.ERR_TYPE_TARGET; 28 | 29 | public NoTargetException() { 30 | this.scimType = SCIM_TYPE; 31 | this.status = 400; 32 | } 33 | 34 | public NoTargetException(String message) { 35 | super(message); 36 | this.scimType = SCIM_TYPE; 37 | this.status = 400; 38 | } 39 | 40 | public NoTargetException(Throwable cause) { 41 | super(cause); 42 | this.scimType = SCIM_TYPE; 43 | this.status = 400; 44 | this.detail = cause.getLocalizedMessage(); 45 | } 46 | 47 | public NoTargetException(String message, Throwable cause) { 48 | super(message, cause); 49 | this.scimType = SCIM_TYPE; 50 | this.status = 400; 51 | this.detail = cause.getLocalizedMessage(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/NotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.independentid.scim.protocol.ScimResponse; 19 | 20 | public class NotFoundException extends ScimException { 21 | 22 | /** 23 | * 24 | */ 25 | private static final long serialVersionUID = 1L; 26 | 27 | public NotFoundException() { 28 | this.status = ScimResponse.ST_NOTFOUND; 29 | } 30 | 31 | public NotFoundException(String message) { 32 | super(message); 33 | this.status = ScimResponse.ST_NOTFOUND; 34 | } 35 | 36 | public NotFoundException(String message, String scimType) { 37 | super(message, scimType); 38 | this.status = ScimResponse.ST_NOTFOUND; 39 | } 40 | 41 | public NotFoundException(Throwable cause) { 42 | super(cause); 43 | this.status = ScimResponse.ST_NOTFOUND; 44 | } 45 | 46 | public NotFoundException(String message, Throwable cause) { 47 | super(message, cause); 48 | this.status = ScimResponse.ST_NOTFOUND; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/NotImplementedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.independentid.scim.protocol.ScimResponse; 19 | 20 | public class NotImplementedException extends ScimException { 21 | 22 | /** 23 | * 24 | */ 25 | private static final long serialVersionUID = 1L; 26 | 27 | public NotImplementedException() { 28 | this.status = ScimResponse.ST_NOSUPPORT; 29 | } 30 | 31 | public NotImplementedException(String message) { 32 | super(message); 33 | this.status = ScimResponse.ST_NOSUPPORT; 34 | } 35 | 36 | public NotImplementedException(String message, String scimType) { 37 | super(message, scimType); 38 | this.status = ScimResponse.ST_NOSUPPORT; 39 | } 40 | 41 | public NotImplementedException(Throwable cause) { 42 | super(cause); 43 | this.status = ScimResponse.ST_NOSUPPORT; 44 | } 45 | 46 | public NotImplementedException(String message, Throwable cause) { 47 | super(message, cause); 48 | this.status = ScimResponse.ST_NOSUPPORT; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/NullValueException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.core.err; 18 | 19 | /** 20 | * This exception used to flag that a Value cannot be constructed because the input was empty or null. Used by virtual attributes. 21 | */ 22 | public class NullValueException extends ScimException { 23 | 24 | public NullValueException(String message) { 25 | super(message); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/PreconditionFailException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.independentid.scim.protocol.ScimResponse; 19 | 20 | /** 21 | * In SCIM, indicates that the ETag hash did not match. 22 | * @author pjdhunt 23 | * 24 | */ 25 | public class PreconditionFailException extends ScimException { 26 | 27 | /** 28 | * 29 | */ 30 | private static final long serialVersionUID = 1L; 31 | 32 | public PreconditionFailException() { 33 | this.status = ScimResponse.ST_PRECONDITION; 34 | this.scimType = null; 35 | this.detail = null; 36 | } 37 | 38 | public PreconditionFailException(String message) { 39 | super(message); 40 | this.status = ScimResponse.ST_PRECONDITION; 41 | this.scimType = null; 42 | 43 | } 44 | 45 | public PreconditionFailException(String message, String scimType) { 46 | super(message, scimType); 47 | this.status = ScimResponse.ST_PRECONDITION; 48 | 49 | } 50 | 51 | public PreconditionFailException(Throwable cause) { 52 | super(cause); 53 | this.status = ScimResponse.ST_PRECONDITION; 54 | } 55 | 56 | public PreconditionFailException(String message, Throwable cause) { 57 | super(message, cause); 58 | this.status = ScimResponse.ST_PRECONDITION; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/ScimException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.fasterxml.jackson.core.JsonGenerator; 19 | import com.independentid.scim.protocol.ScimResponse; 20 | import jakarta.servlet.http.HttpServletResponse; 21 | 22 | import java.io.IOException; 23 | 24 | public class ScimException extends Exception { 25 | 26 | /** 27 | * 28 | */ 29 | private static final long serialVersionUID = 1L; 30 | protected int status = ScimResponse.ST_BAD_REQUEST; 31 | protected String detail = null; 32 | protected String scimType = null; 33 | 34 | public ScimException() { 35 | 36 | } 37 | 38 | public ScimException(String message) { 39 | super(message); 40 | 41 | } 42 | 43 | public ScimException(String message,String scimType) { 44 | super(message); 45 | this.scimType = scimType; 46 | } 47 | 48 | public ScimException(Throwable cause) { 49 | super(cause); 50 | 51 | } 52 | 53 | public ScimException(String message, Throwable cause) { 54 | super(message, cause); 55 | 56 | } 57 | 58 | public int getStatus() { 59 | return this.status; 60 | } 61 | 62 | public void setStatus(int status) { 63 | this.status = status; 64 | } 65 | 66 | public void setDetail(String detailmsg) { 67 | this.detail = detailmsg; 68 | } 69 | 70 | public String getDetail() { 71 | if (this.detail == null) 72 | return this.getMessage(); 73 | else 74 | return this.detail; 75 | } 76 | 77 | public String getScimType() { 78 | return this.scimType; 79 | } 80 | 81 | public void serialize(JsonGenerator gen,HttpServletResponse resp) throws IOException { 82 | gen.writeStartObject(); 83 | gen.writeArrayFieldStart("schemas"); 84 | gen.writeString(ScimResponse.SCHEMA_ERROR); 85 | gen.writeEndArray(); 86 | if (this.scimType != null) 87 | gen.writeStringField("scimType", this.scimType); 88 | if (this.detail != null) 89 | gen.writeStringField("detail",this.detail); 90 | else 91 | gen.writeStringField("detail",this.getLocalizedMessage()); 92 | gen.writeNumberField("status", this.status); 93 | gen.writeEndObject(); 94 | resp.setStatus(this.status); 95 | gen.close(); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/TooLargeException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.independentid.scim.protocol.ScimResponse; 19 | 20 | public class TooLargeException extends ScimException { 21 | 22 | /** 23 | * 24 | */ 25 | private static final long serialVersionUID = 1L; 26 | 27 | public TooLargeException() { 28 | this.status = ScimResponse.ST_TOOLARGE; 29 | } 30 | 31 | public TooLargeException(String message) { 32 | super(message); 33 | this.status = ScimResponse.ST_TOOLARGE; 34 | } 35 | 36 | public TooLargeException(String message, String scimType) { 37 | super(message, scimType); 38 | this.status = ScimResponse.ST_TOOLARGE; 39 | } 40 | 41 | public TooLargeException(Throwable cause) { 42 | super(cause); 43 | this.status = ScimResponse.ST_TOOLARGE; 44 | } 45 | 46 | public TooLargeException(String message, Throwable cause) { 47 | super(message, cause); 48 | this.status = ScimResponse.ST_TOOLARGE; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/TooManyException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | public class TooManyException extends ScimException { 19 | 20 | /** 21 | * 22 | */ 23 | private static final long serialVersionUID = 1L; 24 | 25 | public final static String SCIM_TYPE = "tooMany"; 26 | 27 | public TooManyException() { 28 | this.scimType = SCIM_TYPE; 29 | this.status = 400; 30 | } 31 | 32 | public TooManyException(String message) { 33 | super(message); 34 | this.scimType = SCIM_TYPE; 35 | this.status = 400; 36 | } 37 | 38 | public TooManyException(Throwable cause) { 39 | super(cause); 40 | this.scimType = SCIM_TYPE; 41 | this.status = 400; 42 | this.detail = cause.getLocalizedMessage(); 43 | } 44 | 45 | public TooManyException(String message, Throwable cause) { 46 | super(message, cause); 47 | this.scimType = SCIM_TYPE; 48 | this.status = 400; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/core/err/UnauthorizedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.core.err; 17 | 18 | import com.independentid.scim.protocol.ScimResponse; 19 | 20 | /* 21 | * ForbiddenException is thrown when SCIM client attempts to perform an 22 | * operation that is not permitted based on the supplied authorization. 23 | * See Sec 3.12 of RFC7644. 24 | */ 25 | public class UnauthorizedException extends ScimException { 26 | { status = ScimResponse.ST_UNAUTHORIZED; } 27 | /** 28 | * 29 | */ 30 | private static final long serialVersionUID = 1L; 31 | 32 | public UnauthorizedException() { 33 | 34 | } 35 | 36 | public UnauthorizedException(String message) { 37 | super(message); 38 | 39 | } 40 | 41 | public UnauthorizedException(String message, String scimType) { 42 | super(message, scimType); 43 | } 44 | 45 | public UnauthorizedException(Throwable cause) { 46 | super(cause); 47 | 48 | this.detail = cause.getLocalizedMessage(); 49 | } 50 | 51 | public UnauthorizedException(String message, Throwable cause) { 52 | super(message, cause); 53 | this.detail = cause.getLocalizedMessage(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/events/IEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.events; 18 | 19 | import com.fasterxml.jackson.databind.JsonNode; 20 | import com.independentid.scim.op.Operation; 21 | import jakarta.annotation.PostConstruct; 22 | import jakarta.annotation.PreDestroy; 23 | 24 | public interface IEventHandler { 25 | @PostConstruct 26 | void init(); 27 | 28 | /** 29 | * Takes a JsonNode input and interprets it and then may generate a SCIM {@link Operation} if action 30 | * is to be taken. 31 | * 32 | * @param node A JsonNode parsed event 33 | */ 34 | void consume(Object node); 35 | 36 | /** 37 | * Takes a processed SCIM Operation and publishes it 38 | * @param op A processed SCIM Operation to be published 39 | */ 40 | void publish(Operation op); 41 | 42 | /** 43 | * Indicates if the producer is working. 44 | * @return true if the handler is producing events (no error state) 45 | */ 46 | boolean isProducing(); 47 | 48 | @PreDestroy 49 | void shutdown(); 50 | } 51 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/events/PublishOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.events; 18 | 19 | import com.independentid.scim.backend.BackendHandler; 20 | import com.independentid.scim.core.err.DuplicateTxnException; 21 | import com.independentid.scim.op.Operation; 22 | import com.independentid.scim.resource.TransactionRecord; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | import java.util.Iterator; 27 | import java.util.concurrent.RecursiveAction; 28 | 29 | /** 30 | * This class is used to implement a runnable that will sequence through IEventHandlers discovered to publish events. 31 | * This runnable is invoked by the {@link EventManager}. 32 | */ 33 | public class PublishOperation extends RecursiveAction { 34 | private final static Logger logger = LoggerFactory.getLogger(PublishOperation.class); 35 | 36 | TransactionRecord rec; 37 | BackendHandler backendHandler; 38 | Iterator handlers; 39 | 40 | protected PublishOperation(TransactionRecord rec, Iterator handlerIterator, BackendHandler handler) { 41 | this.rec = rec; 42 | backendHandler = handler; 43 | handlers = handlerIterator; 44 | } 45 | 46 | @Override 47 | protected void compute() { 48 | try { 49 | backendHandler.storeTransactionRecord(rec); 50 | } catch (DuplicateTxnException e) { 51 | logger.error("Duplicate transaction (" + rec.getId() + ") will not be published."); 52 | return; 53 | } 54 | 55 | while (handlers.hasNext()) { 56 | IEventHandler handler = handlers.next(); 57 | Operation op = rec.getOp(); 58 | handler.publish(op); 59 | 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/op/HeadOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.op; 18 | 19 | import com.fasterxml.jackson.core.JsonGenerator; 20 | import jakarta.servlet.http.HttpServletRequest; 21 | import jakarta.servlet.http.HttpServletResponse; 22 | 23 | public class HeadOp extends GetOp { 24 | 25 | public HeadOp(HttpServletRequest req, HttpServletResponse resp) { 26 | super(req, resp); 27 | } 28 | 29 | @Override 30 | public void doSuccess(JsonGenerator gen) { 31 | // don't serialize the result 32 | 33 | if (this.scimresp != null) 34 | this.scimresp.setHeaders(ctx); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/op/IBulkIdResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.op; 17 | 18 | 19 | /** 20 | * @author pjdhunt 21 | * 22 | */ 23 | public interface IBulkIdResolver { 24 | 25 | /** 26 | * @param bulkId 27 | * A bulkId to be translated. The value may begin with "bulkId:" 28 | * or be the plain bulkId to be looked up 29 | * @return A String containing the translated value for the associated 30 | * bulkId. 31 | */ 32 | String translateId(String bulkId); 33 | 34 | /** 35 | * @param bulkId 36 | * A bulkId to be translated. The value may begin with "bulkId:" 37 | * or be the plain bulkId to be looked up 38 | * @return A String containing the translated value for the associated 39 | * bulkId expressed as a URL. 40 | */ 41 | String translateRef(String bulkId); 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/op/IBulkIdTarget.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.op; 17 | 18 | import com.independentid.scim.resource.Value; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * This interface is for targets that may have a temporary batchId value that needs 24 | * to be updated prior to posting to a persistence store. 25 | * @author pjdhunt 26 | * 27 | */ 28 | public interface IBulkIdTarget { 29 | 30 | /** 31 | * @return true if one of the attribute values in the resource has a bulkid: 32 | * prefixed value that needs to be translated 33 | */ 34 | boolean hasBulkIds(); 35 | 36 | /** 37 | * @param bulkList A list provided by the caller which the target will 38 | * update with any attributes that have a bulkId attribute that needs replacing. 39 | */ 40 | void getBulkIdsRequired(List bulkList); 41 | 42 | void getAttributesWithBulkIdValues(List bulkIdAttrs); 43 | } 44 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/op/IBulkOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.op; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.independentid.scim.core.err.ScimException; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * @author pjdhunt 25 | * 26 | */ 27 | public interface IBulkOp { 28 | 29 | boolean hasBulkIdValues(); 30 | 31 | List getBulkIdsRequired(); 32 | 33 | /** 34 | * Tests whether the current operation depends on the operation supplied (is a predicate). 35 | * @param op An Operation value that should execute before the current one. 36 | * @return True if the operation is defined as a predicate operation. 37 | * @throws ScimException may be thrown when a SCIM error occurs (not a child?) 38 | */ 39 | boolean isChildOperation(Operation op) throws ScimException; 40 | 41 | BulkOps getParentBulkRequest(); 42 | 43 | /** 44 | * Generates a bulk request "operation" for the operation performed. Used to propagate replication ops. Note 45 | * that for request, the post-add result is sent to capture generated "id". 46 | * @return A JsonNode representation of operation in Bulk "Operation" format as described in RFC7644 Sec 3.7. If the 47 | * operation did not complete normally, the request returns NULL (because the operation was not processed). 48 | */ 49 | JsonNode getJsonReplicaOp(); 50 | 51 | } 52 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/plugin/IScimPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.plugin; 18 | 19 | import com.independentid.scim.core.err.ScimException; 20 | import com.independentid.scim.op.Operation; 21 | import jakarta.servlet.ServletException; 22 | 23 | public interface IScimPlugin { 24 | 25 | default void init() throws ServletException {} 26 | 27 | void doPreOperation(Operation op) throws ScimException; 28 | 29 | void doPostOperation(Operation op) throws ScimException; 30 | } 31 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/protocol/JsonPatchBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.protocol; 18 | 19 | import com.independentid.scim.resource.Value; 20 | import jakarta.validation.constraints.NotNull; 21 | 22 | public class JsonPatchBuilder { 23 | JsonPatchRequest req; 24 | 25 | JsonPatchBuilder() { 26 | req = new JsonPatchRequest(); 27 | } 28 | 29 | JsonPatchBuilder(JsonPatchOp op) { 30 | req = new JsonPatchRequest(); 31 | req.addOperation(op); 32 | } 33 | 34 | public JsonPatchBuilder withAddOperation(String path, @NotNull Value value) { 35 | JsonPatchOp op = new JsonPatchOp(JsonPatchOp.OP_ACTION_ADD,path,value); 36 | req.addOperation(op); 37 | return this; 38 | } 39 | 40 | public JsonPatchBuilder withRemoveOperation(@NotNull String path) { 41 | JsonPatchOp op = new JsonPatchOp(JsonPatchOp.OP_ACTION_REMOVE,path,null); 42 | req.addOperation(op); 43 | return this; 44 | } 45 | 46 | public JsonPatchBuilder withReplaceOperation(String path, Value value) { 47 | JsonPatchOp op = new JsonPatchOp(JsonPatchOp.OP_ACTION_REPLACE,path,value); 48 | req.addOperation(op); 49 | return this; 50 | } 51 | 52 | public JsonPatchBuilder withOperation(@NotNull JsonPatchOp op) { 53 | req.addOperation(op); 54 | return this; 55 | } 56 | 57 | public JsonPatchRequest build() { 58 | return req; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/protocol/PrecedenceFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.protocol; 18 | 19 | import com.independentid.scim.core.err.BadFilterException; 20 | import com.independentid.scim.resource.ScimResource; 21 | import com.independentid.scim.resource.Value; 22 | import com.independentid.scim.schema.Attribute; 23 | import jakarta.validation.constraints.NotNull; 24 | 25 | import java.util.Set; 26 | 27 | public class PrecedenceFilter extends Filter { 28 | 29 | private boolean isNot = false; 30 | private Filter filter; 31 | 32 | public PrecedenceFilter(String filterStr) { 33 | super(filterStr); 34 | } 35 | 36 | public PrecedenceFilter(Filter subfilter, boolean isNot) { 37 | super(null); 38 | this.isNot = isNot; 39 | this.filter = subfilter; 40 | } 41 | 42 | public boolean isNot() { 43 | return this.isNot; 44 | } 45 | 46 | public Filter getChildFilter() { 47 | return this.filter; 48 | } 49 | 50 | public String toString() { 51 | StringBuilder buf = new StringBuilder(); 52 | if (isNot) 53 | buf.append("not"); 54 | buf.append("("); 55 | if (filter == null) 56 | buf.append("<>"); 57 | else 58 | buf.append(filter.toString()); 59 | buf.append(")"); 60 | return buf.toString(); 61 | } 62 | 63 | public String toValuePathString() { 64 | StringBuilder buf = new StringBuilder(); 65 | if (isNot) 66 | buf.append("not"); 67 | buf.append("("); 68 | if (filter == null) 69 | buf.append("<>"); 70 | else 71 | buf.append(filter.toValuePathString()); 72 | buf.append(")"); 73 | return buf.toString(); 74 | } 75 | 76 | @Override 77 | public boolean isMatch(ScimResource res) throws BadFilterException { 78 | if (isNot) 79 | return !filter.isMatch(res); 80 | return filter.isMatch(res); 81 | 82 | } 83 | 84 | @Override 85 | public boolean isMatch(Value value) throws BadFilterException { 86 | if (isNot) 87 | return !filter.isMatch(value); 88 | return filter.isMatch(value); 89 | } 90 | 91 | @Override 92 | protected void filterAttributes(@NotNull Set attrSet) { 93 | filter.filterAttributes(attrSet); 94 | } 95 | 96 | 97 | 98 | } 99 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/resource/Value.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.resource; 17 | 18 | import com.fasterxml.jackson.core.JsonGenerator; 19 | import com.fasterxml.jackson.databind.JsonNode; 20 | import com.fasterxml.jackson.databind.node.JsonNodeType; 21 | import com.fasterxml.jackson.databind.node.ObjectNode; 22 | import com.independentid.scim.core.err.ConflictException; 23 | import com.independentid.scim.core.err.ScimException; 24 | import com.independentid.scim.protocol.RequestCtx; 25 | import com.independentid.scim.schema.Attribute; 26 | import com.independentid.scim.schema.SchemaException; 27 | 28 | import java.io.IOException; 29 | import java.text.ParseException; 30 | import java.util.HashMap; 31 | 32 | public abstract class Value implements Comparable { 33 | public JsonNodeType jtype; 34 | 35 | Attribute attr; 36 | 37 | public Value() { 38 | 39 | } 40 | 41 | public Value(Attribute attr, JsonNode node) { 42 | if (node != null) 43 | this.jtype = node.getNodeType(); 44 | this.attr = attr; 45 | } 46 | 47 | public abstract void serialize(JsonGenerator gen, RequestCtx ctx) throws ScimException,IOException; 48 | 49 | public abstract void parseJson(JsonNode node) throws ConflictException, SchemaException, ParseException; 50 | 51 | public abstract Object getRawValue(); 52 | 53 | public abstract JsonNode toJsonNode(ObjectNode parent, String aname); 54 | 55 | public String toString(Attribute attr) { 56 | return toJsonNode(null,attr.getName()).toString(); 57 | } 58 | 59 | public Attribute getAttribute() { 60 | return attr; 61 | } 62 | 63 | @Override 64 | public int hashCode() { 65 | return this.getRawValue().hashCode(); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/resource/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * @author pjdhunt 19 | * 20 | */ 21 | package com.independentid.scim.resource; -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/schema/IVirtualValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.schema; 18 | 19 | public interface IVirtualValue { 20 | 21 | boolean isVirtual(); 22 | 23 | void refreshValues(); 24 | } 25 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/schema/SchemaException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.schema; 17 | 18 | 19 | import com.independentid.scim.core.err.ScimException; 20 | 21 | public class SchemaException extends ScimException { 22 | 23 | 24 | /** 25 | * 26 | */ 27 | private static final long serialVersionUID = 1L; 28 | 29 | public SchemaException() { 30 | 31 | } 32 | 33 | public SchemaException(String message) { 34 | super(message); 35 | } 36 | 37 | public SchemaException(Throwable cause) { 38 | super(cause); 39 | } 40 | 41 | public SchemaException(String message, Throwable cause) { 42 | super(message, cause); 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/security/PasswordHandlerPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.security; 18 | 19 | import com.independentid.scim.core.err.ScimException; 20 | import com.independentid.scim.op.Operation; 21 | import com.independentid.scim.plugin.IScimPlugin; 22 | import jakarta.enterprise.context.ApplicationScoped; 23 | import org.eclipse.microprofile.config.inject.ConfigProperty; 24 | 25 | import java.security.SecureRandom; 26 | 27 | @ApplicationScoped 28 | public class PasswordHandlerPlugin implements IScimPlugin { 29 | @ConfigProperty(name="scim.pwd.plugin",defaultValue = "true") 30 | boolean enabled; 31 | 32 | @Override 33 | public void doPreOperation(Operation op) throws ScimException { 34 | if (!enabled) 35 | return; 36 | } 37 | 38 | @Override 39 | public void doPostOperation(Operation op) throws ScimException { 40 | if (!enabled) 41 | return; 42 | String test = "bleh"; 43 | SecureRandom random = new SecureRandom(); 44 | byte[] salt = new byte[16]; 45 | random.nextBytes(salt); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/security/ScimAuthorizationController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.security; 18 | 19 | import com.independentid.scim.core.ConfigMgr; 20 | import io.quarkus.security.spi.runtime.AuthorizationController; 21 | import jakarta.annotation.Priority; 22 | import jakarta.enterprise.context.ApplicationScoped; 23 | import jakarta.enterprise.inject.Alternative; 24 | import jakarta.inject.Inject; 25 | import jakarta.interceptor.Interceptor; 26 | 27 | @Alternative 28 | @Priority(Interceptor.Priority.LIBRARY_AFTER) 29 | @ApplicationScoped 30 | public class ScimAuthorizationController extends AuthorizationController { 31 | @Inject 32 | ConfigMgr cmgr; 33 | 34 | public ScimAuthorizationController() { 35 | super(); 36 | } 37 | 38 | @Override 39 | public boolean isAuthorizationEnabled() { 40 | 41 | return cmgr.isSecurityEnabled(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/serializer/ScimResponseSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.serializer; 18 | 19 | import com.fasterxml.jackson.core.JsonGenerator; 20 | import com.fasterxml.jackson.databind.JsonSerializer; 21 | import com.fasterxml.jackson.databind.SerializerProvider; 22 | import com.independentid.scim.protocol.ScimResponse; 23 | 24 | import java.io.IOException; 25 | 26 | public class ScimResponseSerializer extends JsonSerializer { 27 | 28 | //TODO: Is this needed? 29 | 30 | @Override 31 | public void serialize(ScimResponse value, JsonGenerator gen, SerializerProvider serializers) throws IOException { 32 | // TODO Auto-generated method stub 33 | throw new IOException("NOT IMPLEMENTED!"); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /i2scim-core/src/main/java/com/independentid/scim/serializer/ScimSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.independentid.scim.serializer; 17 | 18 | import com.fasterxml.jackson.core.JsonGenerator; 19 | import com.fasterxml.jackson.databind.JsonNode; 20 | import com.independentid.scim.core.err.ConflictException; 21 | import com.independentid.scim.core.err.ScimException; 22 | import com.independentid.scim.protocol.RequestCtx; 23 | import com.independentid.scim.schema.SchemaException; 24 | 25 | import java.io.IOException; 26 | import java.text.ParseException; 27 | 28 | public interface ScimSerializer { 29 | 30 | void parseJson(JsonNode node) throws SchemaException, ParseException, ConflictException; 31 | 32 | /** 33 | * toJsonNode is useful for doing deep copies and translations to avoid full serialization into strings. 34 | * @return An ObjectNode cast as JsonNode representation of the full object. This method does NOT provide security filtering. 35 | */ 36 | JsonNode toJsonNode(); 37 | 38 | void serialize(JsonGenerator gen, RequestCtx ctx) throws IOException, ScimException; 39 | 40 | void serialize(JsonGenerator gen, RequestCtx ctx, boolean forHash) throws IOException, ScimException; 41 | } 42 | -------------------------------------------------------------------------------- /i2scim-prov-memory/src/main/java/com/independentid/scim/backend/memory/MemoryIdGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.backend.memory; 18 | 19 | import com.independentid.scim.backend.IIdentifierGenerator; 20 | import jakarta.annotation.Priority; 21 | import jakarta.enterprise.context.ApplicationScoped; 22 | import jakarta.enterprise.inject.Default; 23 | import jakarta.inject.Named; 24 | 25 | import java.util.UUID; 26 | 27 | @ApplicationScoped 28 | @Named("MemoryIdGen") 29 | public class MemoryIdGenerator implements IIdentifierGenerator { 30 | 31 | /** 32 | * Generates and obtains an identifier usable for objects within the persistence provider. This is most typically 33 | * used for generating transactionIds which will be ultimately stored in the providers "Trans" container. 34 | * @return A String value that can be used as an object identifier. 35 | */ 36 | @Override 37 | public String getNewIdentifier() { 38 | return UUID.randomUUID().toString(); 39 | } 40 | 41 | @Override 42 | public String getProviderClass() { 43 | return MemoryProvider.class.getName(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /i2scim-prov-memory/src/main/java/com/independentid/scim/backend/memory/ValResMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.backend.memory; 18 | 19 | import com.independentid.scim.resource.Value; 20 | 21 | import java.util.*; 22 | 23 | public class ValResMap implements Comparable{ 24 | 25 | Value val; 26 | 27 | Set idList = new HashSet<>(); 28 | 29 | public ValResMap(Value value) { 30 | this.val = value; 31 | } 32 | 33 | public void addId(String id) { 34 | idList.add(id); 35 | } 36 | 37 | public void removeId(String id) { 38 | idList.remove(id); 39 | } 40 | 41 | public boolean containsId(String id) { 42 | return idList.contains(id); 43 | } 44 | 45 | public Set getIds() { 46 | return idList; 47 | } 48 | 49 | public Value getKey() { return val;} 50 | 51 | 52 | @Override 53 | public int compareTo(ValResMap o) { 54 | return val.compareTo(o.getKey()); 55 | 56 | } 57 | 58 | @Override 59 | public boolean equals(Object obj) { 60 | if (obj instanceof ValResMap) 61 | return val.equals(((ValResMap)obj).getKey()); 62 | return false; 63 | } 64 | 65 | public int size() { 66 | return idList.size(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /i2scim-prov-mongo/src/main/java/com/independentid/scim/backend/mongo/MongoDateConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.backend.mongo; 18 | 19 | import java.util.Date; 20 | 21 | import org.bson.json.Converter; 22 | import org.bson.json.StrictJsonWriter; 23 | 24 | import com.independentid.scim.resource.Meta; 25 | 26 | public class MongoDateConverter implements Converter { 27 | 28 | @Override 29 | public void convert(Long value, StrictJsonWriter writer) { 30 | //Instant ins = new Date(value).toInstant(); 31 | String sdate = Meta.ScimDateFormat.format(new Date(value)); 32 | writer.writeString(sdate); 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /i2scim-prov-mongo/src/main/java/com/independentid/scim/backend/mongo/MongoIdGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.backend.mongo; 18 | 19 | import com.independentid.scim.backend.IIdentifierGenerator; 20 | import jakarta.annotation.Priority; 21 | import jakarta.enterprise.context.ApplicationScoped; 22 | import org.bson.types.ObjectId; 23 | 24 | @ApplicationScoped 25 | @Priority(10) 26 | public class MongoIdGenerator implements IIdentifierGenerator { 27 | 28 | /** 29 | * Generates and obtains an identifier usable for objects within the persistence provider. This is most typically 30 | * used for generating transactionIds which will be ultimately stored in the providers "Trans" container. 31 | * @return A String value that can be used as an object identifier. 32 | */ 33 | @Override 34 | public String getNewIdentifier() { 35 | return (new ObjectId()).toString(); 36 | } 37 | 38 | @Override 39 | public String getProviderClass() { 40 | return MongoProvider.class.getName(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /i2scim-prov-mongo/src/main/java/com/independentid/scim/backend/mongo/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | /** 17 | * @author pjdhunt 18 | * 19 | */ 20 | package com.independentid.scim.backend.mongo; -------------------------------------------------------------------------------- /i2scim-signals/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Store -------------------------------------------------------------------------------- /i2scim-signals/src/main/java/com/independentid/signals/EventTypes.java: -------------------------------------------------------------------------------- 1 | package com.independentid.signals; 2 | 3 | public class EventTypes { 4 | 5 | public final static String PROV_CREATE_FULL = "urn:ietf:params:SCIM:event:prov:create:full"; 6 | public final static String PROV_CREATE_NOTICE = "urn:ietf:params:SCIM:event:prov:create:notice"; 7 | public final static String PROV_PUT_FULL = "urn:ietf:params:SCIM:event:prov:put:full"; 8 | public final static String PROV_PUT_NOTICE = "urn:ietf:params:SCIM:event:prov:put:notice"; 9 | public final static String PROV_PATCH_FULL = "urn:ietf:params:SCIM:event:prov:patch:full"; 10 | public final static String PROV_PATCH_NOTICE = "urn:ietf:params:SCIM:event:prov:patch:notice"; 11 | public final static String PROV_DELETE = "urn:ietf:params:SCIM:event:prov:delete"; 12 | public final static String PROV_ACTIVATE = "urn:ietf:params:SCIM:event:prov:activate"; 13 | public final static String PROV_DEACTIVATE = "urn:ietf:params:SCIM:event:prov:deactivate"; 14 | 15 | public final static String MISC_ASYNC_RESP = "urn:ietf:params:SCIM:event:misc:asyncResp"; 16 | } 17 | -------------------------------------------------------------------------------- /i2scim-signals/src/main/resources/application-testing.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021. Independent Identity Incorporated 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | scim.mongodb.uri=mongodb://localhost:27017 17 | scim.mongodb.dbname=SCIM 18 | scim.resourcetype.path=classpath:/schema/resourceTypes.json 19 | scim.json.pretty=true 20 | scim.schema.path=classpath:/schema/scimSchema.json 21 | logging.level.com.independentid.scim=DEBUG 22 | scim.provider.bean=com.independentid.scim.backend.mongo.MongoProvider 23 | quarkus.http.access-log.enabled=true 24 | quarkus.http.access-log.log-to-file=true 25 | quarkus.http.access-log.base-file-name=scim-access 26 | quarkus.http.access-log.log-directory=./logs -------------------------------------------------------------------------------- /i2scim-signals/src/main/resources/schema/acis.json: -------------------------------------------------------------------------------- 1 | { 2 | "acis": [ 3 | { 4 | "path": "/", 5 | "name": "Self and employee access to read information", 6 | "targetAttrs": "*,-password", 7 | "targetFilter": "meta.resourceType eq User", 8 | "rights": "read, search, compare", 9 | "actors": [ 10 | "self", 11 | "filter=employeeNumber pr" 12 | ] 13 | }, 14 | { 15 | "path": "/", 16 | "name": "Administrators can read, search, compare all records and operational attributes", 17 | "targetAttrs": "*", 18 | "rights": "read, search, compare", 19 | "actors": [ 20 | "role=admin root" 21 | ] 22 | }, 23 | { 24 | "path": "/", 25 | "name": "Admins can update all resources", 26 | "targetAttrs": "*", 27 | "rights": "add, modify, delete", 28 | "actors": [ 29 | "role=admin root" 30 | ] 31 | }, 32 | { 33 | "path": "/Users", 34 | "name": "Allow unauthenticated access to names and email addresses of Users", 35 | "targetFilter": "meta.resourceType eq User", 36 | "targetAttrs": "username,displayName,emails,name,phoneNumbers", 37 | "rights": "read, search, compare", 38 | "actors": [ 39 | "any" 40 | ] 41 | }, 42 | { 43 | "path": "/ServiceProviderConfig", 44 | "name": "Allow unauthenticated access to ServiceProviderConfig", 45 | "targetAttrs": "*", 46 | "rights": "read, search, compare", 47 | "actors": [ 48 | "any" 49 | ] 50 | }, 51 | { 52 | "path": "/ResourceTypes", 53 | "name": "Allow unauthenticated access to ResourceTypes", 54 | "targetAttrs": "*", 55 | "rights": "read, search, compare", 56 | "actors": [ 57 | "any" 58 | ] 59 | }, 60 | { 61 | "path": "/Schemas", 62 | "name": "Allow unauthenticated access to Schemas", 63 | "targetAttrs": "*", 64 | "rights": "read, search, compare", 65 | "actors": [ 66 | "any" 67 | ] 68 | } 69 | ] 70 | } -------------------------------------------------------------------------------- /i2scim-signals/src/test/java/com/independentid/scim/test/events/SignalsEventTestProfile.java: -------------------------------------------------------------------------------- 1 | package com.independentid.scim.test.events; 2 | 3 | import com.independentid.scim.backend.memory.MemoryProvider; 4 | import io.quarkus.test.junit.QuarkusTestProfile; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /* 12 | This profile is sets up testing to validate the SignalsEventHandler for end-to-end processing. 13 | */ 14 | public class SignalsEventTestProfile implements QuarkusTestProfile { 15 | 16 | public Map getConfigOverrides() { 17 | String cfgFile = "cfg.json"; 18 | try { 19 | File tempFile = File.createTempFile("SsfConfig", ".json"); 20 | cfgFile = tempFile.toString(); 21 | } catch (IOException e) { 22 | throw new RuntimeException(e); 23 | } 24 | 25 | HashMap map = new HashMap<>(Map.of( 26 | "scim.prov.providerClass", MemoryProvider.class.getName(), 27 | 28 | "quarkus.log.min-level", "DEBUG", 29 | "logging.level.com.independentid.scim", "DEBUG", 30 | "quarkus.log.category.\"com.independentid.scim.test\".level", "DEBUG", 31 | "scim.root.dir", ".", 32 | "scim.security.enable", "false", 33 | 34 | "scim.event.enable", "true" 35 | )); 36 | 37 | map.putAll(Map.of( 38 | "scim.signals.enable", "true", // Enable the SignalEventHandler. 39 | "scim.signals.ssf.configFile", cfgFile, 40 | "scim.signals.pub.pem.path", "/data/issuer.pem", 41 | "scim.signals.pub.iss", "myissuer.io", 42 | "scim.signals.pub.aud", "example.com", 43 | "scim.signals.rcv.iss", "myissuer.io", 44 | "scim.signals.test", "true", 45 | "scim.signals.rcv.iss.jwksJson", "{\"keys\":[{\"e\":\"AQAB\",\"kid\":\"myissuer.io\",\"kty\":\"RSA\",\"n\":\"rCPRnmNNptz1Y4QIAwbDDiXgYvB2PV_X2_LCtEOaV68_wxynXVErPQzJvpA6Zlr1dn0w1H2azxw_G1jgQAcw7yg3YWEQCh89kwcRZVA33dwtIMIatNtwIKB40nbW4-NoHwg2UfiyG7i2xO8VMi4N-hBp8qnhrR2JvWAuhykKwLEXdyl9-0rGBlxxruvqkJsnrhEiMQkk9-B2mw36CsL1XHd9GFTLcNF8Gc55oI36qsMqTDRQZtHbc19WGwEopunuEqkG1AAsRzAlyjS_-KMT5biVB1WXOz5WC_6XBrdlK_pWNDIEOUG0jzS18eenHb3ZeefpJp6M1vs09Rc67nHqvw\"}]}", "scim.signals.rcv.aud", "example.com" 46 | )); 47 | return map; 48 | } 49 | 50 | @Override 51 | public String getConfigProfile() { 52 | return "SignalsEventTestProfile"; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /i2scim-signals/src/test/java/com/independentid/scim/test/events/TestUtils.java: -------------------------------------------------------------------------------- 1 | package com.independentid.scim.test.events; 2 | 3 | 4 | import com.independentid.scim.backend.BackendException; 5 | import com.independentid.scim.backend.memory.MemoryProvider; 6 | import com.independentid.scim.core.err.ScimException; 7 | import com.independentid.scim.schema.SchemaManager; 8 | import jakarta.annotation.Priority; 9 | import jakarta.annotation.Resource; 10 | import jakarta.inject.Inject; 11 | import jakarta.inject.Singleton; 12 | import org.eclipse.microprofile.config.inject.ConfigProperty; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import java.io.File; 17 | import java.io.IOException; 18 | import java.net.MalformedURLException; 19 | import java.net.URL; 20 | 21 | @Singleton 22 | @Priority(6) 23 | public class TestUtils { 24 | 25 | private static final Logger logger = LoggerFactory.getLogger(TestUtils.class); 26 | 27 | @Inject 28 | @Resource(name = "SchemaMgr") 29 | SchemaManager smgr; 30 | 31 | @ConfigProperty(name = "scim.prov.memory.persist.dir", defaultValue = "./scimdata") 32 | String storeDir; 33 | 34 | @Inject 35 | MemoryProvider memoryProvider; 36 | 37 | public static String mapPathToReqUrl(URL baseUrl, String path) throws MalformedURLException { 38 | URL rUrl = new URL(baseUrl, path); 39 | return rUrl.toString(); 40 | } 41 | 42 | public void resetMemoryDb() throws ScimException, BackendException, IOException { 43 | logger.warn("\t*** Resetting Memory Provider Data [" + storeDir + "] ***"); 44 | // Shut the provider down 45 | if (memoryProvider.ready()) 46 | memoryProvider.shutdown(); 47 | smgr.resetConfig(); 48 | 49 | resetMemDirectory(); 50 | 51 | // restart and reload 52 | smgr.init(); 53 | memoryProvider.init(); 54 | 55 | } 56 | 57 | public void resetMemDirectory() { 58 | // Reset the memory provider 59 | logger.warn("\t*** Resetting Memory database files in " + storeDir + " ***"); 60 | File memdir = new File(storeDir); 61 | File[] files = memdir.listFiles(); 62 | if (files != null) 63 | for (File afile : files) 64 | afile.delete(); 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /i2scim-signals/src/test/java/com/independentid/scim/test/set/SignalsSetTestProfile.java: -------------------------------------------------------------------------------- 1 | package com.independentid.scim.test.set; 2 | 3 | import com.independentid.scim.backend.memory.MemoryProvider; 4 | import io.quarkus.test.junit.QuarkusTestProfile; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /* 10 | This profile is used to test the mapper and other functions but does not turn on the event handler. 11 | */ 12 | 13 | public class SignalsSetTestProfile implements QuarkusTestProfile { 14 | public Map getConfigOverrides() { 15 | 16 | return new HashMap<>(Map.of( 17 | "scim.prov.providerClass", MemoryProvider.class.getName(), 18 | 19 | "quarkus.log.min-level", "DEBUG", 20 | "logging.level.com.independentid.scim", "DEBUG", 21 | "quarkus.log.category.\"com.independentid.scim.test\".level", "DEBUG", 22 | "scim.root.dir", ".", //enables local debug testing 23 | 24 | "scim.security.enable", "false", 25 | "scim.signals.enable", "false", 26 | "scim.event.enable", "true" 27 | // "scim.signals.stream.receiver.jwksUrl","NONE" 28 | )); 29 | } 30 | 31 | @Override 32 | public String getConfigProfile() { 33 | return "SignalsEventMinTestProfile"; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /i2scim-signals/src/test/java/com/independentid/scim/test/ssf/SignalsSsfTestProfile.java: -------------------------------------------------------------------------------- 1 | package com.independentid.scim.test.ssf; 2 | 3 | import com.independentid.scim.backend.memory.MemoryProvider; 4 | import io.quarkus.test.junit.QuarkusTestProfile; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /* 12 | This profile is sets up testing to confirm the MockSignals server and test StreamHandler class. EventHandler is disabled. 13 | */ 14 | public class SignalsSsfTestProfile implements QuarkusTestProfile { 15 | 16 | public Map getConfigOverrides() { 17 | String cfgFile = "cfg.json"; 18 | try { 19 | File tempFile = File.createTempFile("SsfConfig", ".json"); 20 | cfgFile = tempFile.toString(); 21 | } catch (IOException e) { 22 | throw new RuntimeException(e); 23 | } 24 | HashMap map = new HashMap<>(Map.of( 25 | "scim.prov.providerClass", MemoryProvider.class.getName(), 26 | 27 | "quarkus.log.min-level", "DEBUG", 28 | "logging.level.com.independentid.scim", "DEBUG", 29 | "quarkus.log.category.\"com.independentid.scim.test\".level", "DEBUG", 30 | "scim.root.dir", ".", 31 | "scim.security.enable", "false", 32 | 33 | "scim.event.enable", "true" 34 | )); 35 | 36 | map.putAll(Map.of( 37 | "scim.signals.test", "true", 38 | "scim.signals.enable", "false", 39 | "scim.signals.ssf.configFile", cfgFile, 40 | "scim.signals.pub.pem.path", "/data/issuer.pem", 41 | "scim.signals.pub.iss", "myissuer.io", 42 | "scim.signals.pub.aud", "example.com", 43 | "scim.signals.rcv.iss", "myissuer.io", 44 | "scim.signals.rcv.iss.jwksJson", "{\"keys\":[{\"e\":\"AQAB\",\"kid\":\"myissuer.io\",\"kty\":\"RSA\",\"n\":\"rCPRnmNNptz1Y4QIAwbDDiXgYvB2PV_X2_LCtEOaV68_wxynXVErPQzJvpA6Zlr1dn0w1H2azxw_G1jgQAcw7yg3YWEQCh89kwcRZVA33dwtIMIatNtwIKB40nbW4-NoHwg2UfiyG7i2xO8VMi4N-hBp8qnhrR2JvWAuhykKwLEXdyl9-0rGBlxxruvqkJsnrhEiMQkk9-B2mw36CsL1XHd9GFTLcNF8Gc55oI36qsMqTDRQZtHbc19WGwEopunuEqkG1AAsRzAlyjS_-KMT5biVB1WXOz5WC_6XBrdlK_pWNDIEOUG0jzS18eenHb3ZeefpJp6M1vs09Rc67nHqvw\"}]}", "scim.signals.rcv.aud", "example.com" 45 | )); 46 | 47 | map.putAll(Map.of( 48 | "quarkus.http.auth.permission.permit1.paths=", "/*", 49 | "quarkus.http.auth.permission.permit1.policy", "permit", 50 | "quarkus.http.auth.permission.permit1.methods", "GET,POST,HEAD,DELETE,PATCH" 51 | )); 52 | return map; 53 | } 54 | 55 | @Override 56 | public String getConfigProfile() { 57 | return "SignalsEventTestProfile"; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /i2scim-signals/src/test/resources/certs/jwks-certs.json: -------------------------------------------------------------------------------- 1 | { 2 | "keys": [ 3 | { 4 | "kty": "RSA", 5 | "kid": "i2scim", 6 | "use": "Key used for i2scim testing purposes ONLY!", 7 | "n": "taCP35lFs85YNnjpKqbCASaosD7QdZjGnDqWoZs93wbYHbqGRMEVQ4YInNd5MsZKcF3gGtHqo0DVM_CDiRIZxcZZuwZ3BBtRmBuQafytOCkNZKjfoOE6ptnHO9oTkyhKiNJIs-lKRldP-SDUHZ_Oux8dAnD-kJhjijInRJJkqsaO-gH26sv95O7k5S0Jm-ERr0Tqfostf0k_YM9elYXXzh7CQi3rGZ9h-ccckkcs8i-J4BVVsBDruO5Rxvtt5KVEUp0PuCrLLuqmCuhjL-JdE4EiuomdJDbAqmmQZ6Ef6g_nUH_4WcCtDtN_LerTgEzIz9D7i8NV_0Ho311R9Lt4GQ", 8 | "e": "AQAB" 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /i2scim-signals/src/test/resources/data/issuer.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCsI9GeY02m3PVj 3 | hAgDBsMOJeBi8HY9X9fb8sK0Q5pXrz/DHKddUSs9DMm+kDpmWvV2fTDUfZrPHD8b 4 | WOBABzDvKDdhYRAKHz2TBxFlUDfd3C0gwhq023AgoHjSdtbj42gfCDZR+LIbuLbE 5 | 7xUyLg36EGnyqeGtHYm9YC6HKQrAsRd3KX37SsYGXHGu6+qQmyeuESIxCST34Hab 6 | DfoKwvVcd30YVMtw0XwZznmgjfqqwypMNFBm0dtzX1YbASim6e4SqQbUACxHMCXK 7 | NL/4oxPluJUHVZc7PlYL/pcGt2Ur+lY0MgQ5QbSPNLXx56cdvdl55+kmnozW+zT1 8 | Fzruceq/AgMBAAECggEAdXDailzllXoaUJK7hJUQbo6Yz+eOQ8En2/97ptCYdEo0 9 | DkF2Tcwa28PlwAVWUo6r+PLgZZhsDfEPfPDdzdEaKZAeeGloL/+wWqbvz1czRkH4 10 | 5+iFn+42SYwx4iUB5ug3GTTZGoO5v//9cc5Lf7i8AGdCYTRVq24DkxgTplLx6xPI 11 | onjFOgpunT3wnVo/D5ZNJJiTQPDkrAsioKiPkEKl6ShijqcdDfMs+0sSBrH4YLxA 12 | fmZT0tiME/IoPxD8s8V1IPZG3i+AGRV67Mo8R/M/qFpSLggQtBQ4cdZtCqBKv8xc 13 | D2Qatj2KJ031omeBlJ0pQTGpF/Qdm3CUSvQt82hHwQKBgQDT6zT/qwli3e/ZE3aL 14 | hQiNf/9azqk5YwFa4pxNlrS/8E6u66mftlO4kKt+l9IJIousmYQpWlazn5gNHHor 15 | o/tSopLrHleEjcR+Wjtr1Jj9tgNYpdezi7d27vTS3jfSjFvNpFd0Q7iimPmLt5Yt 16 | +g7WQTrf9lqY7Zx2qKPXEHD5HQKBgQDP8l2GOLbHp4FEIBdbDLudpP2IwtxK3zaC 17 | qq87uW+wzCELDcl41Xf5xtWtqR4nMv6MnXERPTzSd9wCrX4Uqj4eQ4uNJCXk0ubM 18 | euRAqVUdxO1JKH+XZdhsSxPw8uB2umt8Q9FX+Q+YUuR5msCpwoo+dKmt2HmDDW2t 19 | VLFbq6zIiwKBgQCiHYHKwDYK+wsbvgbmzptvW+alugi8zN9hfo/hzxNw7c3ThJab 20 | hmhffdSjoFLeCB5fqITw+ZnwCXvRM+LF9ckyOwo3cVu0HJufqTlh0R5EoHPI4f2z 21 | 7YMpKb4Cflqn6BXmp/z7BT9+q5Xja0so2u10vCvk3toJuWQDZhkIUhyKhQKBgHTS 22 | gjwvjG/p6LMvHC/onVZZJJ46aqwdbnBGF6AD831tkHq3SiJ6Oqa2T8D6K5h2C49P 23 | u/+lWZAcChvu/8/4PGGgLLwkPK2q1kK2H5k8CDdrNKtO9y9E5isgmplYuUW6QTxU 24 | lT1JDLvUhcrTZ713L1cbD2A9Jza6yoz/8YvAjJc1AoGAaCfpwblf5Dsr1bLlyFuw 25 | zQqMQvBIJAarjc04HUenaanJxNFIkXAKbBrZo3N4jfqusDwIRjsAAJpbu5p8gEkH 26 | hheNFqccceQMifzABkHEKsXBbEXnrTXCDmDyXhKs289PQzKRRYanNio9ELKvcSaf 27 | /quL4CEC16teE+JH5KdV8TA= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /i2scim-signals/src/test/resources/data/jwk-sign.json: -------------------------------------------------------------------------------- 1 | { 2 | "kty": "RSA", 3 | "kid": "i2scim", 4 | "use": "Key used for i2scim testing purposes ONLY!", 5 | "n": "taCP35lFs85YNnjpKqbCASaosD7QdZjGnDqWoZs93wbYHbqGRMEVQ4YInNd5MsZKcF3gGtHqo0DVM_CDiRIZxcZZuwZ3BBtRmBuQafytOCkNZKjfoOE6ptnHO9oTkyhKiNJIs-lKRldP-SDUHZ_Oux8dAnD-kJhjijInRJJkqsaO-gH26sv95O7k5S0Jm-ERr0Tqfostf0k_YM9elYXXzh7CQi3rGZ9h-ccckkcs8i-J4BVVsBDruO5Rxvtt5KVEUp0PuCrLLuqmCuhjL-JdE4EiuomdJDbAqmmQZ6Ef6g_nUH_4WcCtDtN_LerTgEzIz9D7i8NV_0Ho311R9Lt4GQ", 6 | "e": "AQAB", 7 | "d": "rUvk2uDAq94PNvJI72QrKbP8MiXM-tdpcXlJbirUbu9112-4WvOr2UCTCStivbqLHgnEIXL3IQtkIemzZ1647obh6NwzRNzYDn0GXsozcKli2Q90SGl-b-LNAWODV96St1eE_Pxz3QfEC51yJk3rj4kRQdoUWly8ZQiThQ71NCciiSjk38y5aHYBg1frya5wWwQ9iMyDlfni4v8YNF1JGIiBsi0akgwAmtfbAAWE21nbgQIzytIi_dBgUSI-Tri5YFpxcU_E2qntme_1MJf-pl4789AFCPz2qcyL4Ty2kA66COHOBh51yHhuG9sVe5y74XI12ufDk6gOUuRef5WNLQ", 8 | "p": "24RJ2EbGL_S-Lm_FjX7QpOauYSf9dojZJiEaTZqtNpS_SzMshmhvzaatQyEpjkfgUxQvVnsFGRRDvDjPjRjBhLQZoGDQv3IGq-mGiFgkVkv17DXZOr7PzIwEHhezpKKac7agemguVJU8AfByWXywkhsEfFfsDzNVPCEPnESlrfM", 9 | "q": "09AywizydrQD8wosV8Gxq3wjjybAj2q_7XCUx8xcfIjiLjQhYF9UJOET9Ge-E0IJheNvlGQwQ5Z91BF0Wx7L5pbg_9SnrdppvP3aPM0NW8GqU2jFt_n1xOATt0FrmNvnqizfKjKdWsz14an9GXBIoyvPZOkaXMmkPo3tJt--KMM", 10 | "dp": "EC51PxMgguJ4rnWgy2hguvciPZk0DuvRjgT8qmHPiOl4HHP-QT4rl65EsWEdbhaQS69-OdLBsnKS96n8ars7cKvSA8d_O82M_lktiJluvEnHLA1gIPt11-8uUoWOwYEW_5ajx8IsQCHsFXyDAWO2pF6Hex8EEK7JBrCtNOi-ic8", 11 | "dq": "NMp5PCgTrj4jldl9P8oIzCK-ghk4eQY0G6upiTqH-onrRXS8tNZNlHt8i7enigk1cmdDEgr-dHn3lnlbNLKyQyBrp5eKyyvamr3yPKEmqS3Vk8BTNw1Xkd__SfdGJ-z3ClTwsgW3bkATMFE7wbFYiUKMCCyI44NmKikZaEzvih0", 12 | "qi": "ASpt1BVH6l7Sce-7m-VEY64XtZDcZet92XWKyiUXZysk0oxVmlSemf6oJwpqZJY9So3rAEhNiO-OgDxsN7QuO9dJP88SVxfUIlNfk46lSKZb_ZkmHePIy0Ff1sCL7W6kiNeN8mLWGNwdhjlcyAboiGG0j5y1gHE4CDmeWqpuLnw" 13 | } -------------------------------------------------------------------------------- /i2scim-signals/src/test/resources/data/pubStream.json: -------------------------------------------------------------------------------- 1 | { 2 | "alias": "sQs", 3 | "id": "6525f54e86b849e69ca1a779", 4 | "description": "Push Receiver", 5 | "token": "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkRFRkFVTFQiLCJ0eXAiOiJqd3QifQ.eyJzaWQiOlsiNjUyNWY1NGU4NmI4NDllNjljYTFhNzc5Il0sInByb2plY3RfaWQiOiJBa0NVIiwicm9sZXMiOlsiZXZlbnQiXSwiaXNzIjoiREVGQVVMVCIsImF1ZCI6WyJERUZBVUxUIl0sImV4cCI6MTcwNDc2MjQ0NiwiaWF0IjoxNjk2OTg2NDQ2LCJqdGkiOiIyV2IxUUNoNTBjc2RBVUIyTFZtOTlnYzFYazMifQ.Tk5M7yn64kkfxr_ds9CJXMcifvefxxftq4e_gX9-KZzViUyd1SBNofz-_Dfzh5zIMsl0XBiLXLRofQU_yhsh_yGKGz6_9TlOzmwA3tNclJEeaCySOvtyUZ39D773u60Ss3ydXvTUtai8WE5PV5Qmu3wvyTSiABrTIbTv260MOLuk1hisPYQmpNE06BMCv3LIeBaMggZrJKJRTkCmgxHlgdVUh4BAPRlqiKG0jiCED1z6PHsMUaocT_1gVQEuchRdGgZTRBglMCAVSQibBLqOA6d1BrLGVGUKOMtJNj4tb59TrKpM--QCqAksNM02Kj1nOiiac7tR1BcnxBULhAj3gA", 6 | "endpoint": "http://goSignals1:8888/events/6525f54e86b849e69ca1a779", 7 | "iss": "myissuer.io", 8 | "aud": "myissuer.io", 9 | "issJwksUrl": "" 10 | } 11 | -------------------------------------------------------------------------------- /i2scim-signals/src/test/resources/data/receiveStream.json: -------------------------------------------------------------------------------- 1 | { 2 | "alias": "rMy", 3 | "id": "6525f6a386b849e69ca1a77d", 4 | "description": "Poll Publisher", 5 | "token": "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkRFRkFVTFQiLCJ0eXAiOiJqd3QifQ.eyJzaWQiOlsiNjUyNWY2YTM4NmI4NDllNjljYTFhNzdkIl0sInByb2plY3RfaWQiOiJBa0NVIiwicm9sZXMiOlsiZXZlbnQiXSwiaXNzIjoiREVGQVVMVCIsImF1ZCI6WyJERUZBVUxUIl0sImV4cCI6MTcwNDc2Mjc4NywiaWF0IjoxNjk2OTg2Nzg3LCJqdGkiOiIyV2IyNzRDRGNnQThwcUs1WDJadmw1VDd3RUgifQ.dttFa-fcdeYdU00x2fPrY4DQVuXbeiWUjXNlIVlh_ST-9p6om6Al0q6Ucwge8L2B8V9y2dwfEZYKma8KsqBaeckKSMsLy1npPgWIRkiKuFY1k7tv7XGd8KfnzEuzqCaIQNt8M8i97hkmKlhf9OfsQ4HrJN_n3pRpEJXjIec90HQwItH-8XNBBF5CbHIinPjpFlizTd0c7SOHiWsgb3-LwQmAbLo1byNTMC-1ekz3N6xd79USB-qNWj56Ie_JZ-ijt7_3vf72zKM1N9MUNw3l7_U8MxaNf-T0y55q4VKzcGd0gDpY3LnpF_Mg8-l01LHEcvLkoMqF0Xgh4mrxIW2tvQ", 6 | "endpoint": "http://goSignals1:8888/poll/6525f6a386b849e69ca1a77d", 7 | "iss": "myissuer.io", 8 | "aud": "myissuer.io", 9 | "issJwksUrl": "/jwks/myissuer.io" 10 | } 11 | -------------------------------------------------------------------------------- /i2scim-signals/src/test/resources/schema/aciSecurityTest.json: -------------------------------------------------------------------------------- 1 | { 2 | "acis": [ 3 | { 4 | "path": "/", 5 | "name": "Administrators can read, search, compare all records and operational attributes", 6 | "targetAttrs": "*", 7 | "rights": "read, search, compare", 8 | "actors": [ 9 | "role=root admin full" 10 | ] 11 | }, 12 | { 13 | "path": "/", 14 | "name": "Root can update all systems", 15 | "targetAttrs": "*", 16 | "rights": "add, modify, delete", 17 | "actors": [ 18 | "role=root admin full" 19 | ] 20 | }, 21 | { 22 | "path": "/Users", 23 | "name": "Users can read self except userType", 24 | "targetAttrs": "*,-userType,-ims", 25 | "rights": "read,search", 26 | "actors": [ 27 | "self" 28 | ] 29 | }, 30 | { 31 | "path": "/Users", 32 | "name": "Users can self-modify some attributes", 33 | "targetAttrs": "displayName, emails, nickName, addresses, phoneNumbers", 34 | "rights": "modify", 35 | "actors": [ 36 | "self" 37 | ] 38 | }, 39 | { 40 | "path": "/Users", 41 | "name": "Allow unauthenticated access to names and email addresses of Users", 42 | "targetFilter": "meta.resourceType eq User", 43 | "targetAttrs": "username,displayName,emails,name,phoneNumbers", 44 | "rights": "read", 45 | "actors": [ 46 | "role=user bearer root" 47 | ] 48 | }, 49 | { 50 | "path": "/Users", 51 | "name": "Allow unauthenticated access to names and email addresses of Users", 52 | "targetFilter": "meta.resourceType eq User", 53 | "targetAttrs": "username", 54 | "rights": "search", 55 | "actors": [ 56 | "role=user bearer root" 57 | ] 58 | }, 59 | { 60 | "path": "/ServiceProviderConfig", 61 | "name": "Allow unauthenticated access to ServiceProviderConfig", 62 | "targetAttrs": "*", 63 | "rights": "read, search", 64 | "actors": [ 65 | "any" 66 | ] 67 | }, 68 | { 69 | "path": "/Schemas", 70 | "name": "Allow authenticated access to Schemas", 71 | "targetAttrs": "*", 72 | "rights": "read, search", 73 | "actors": [ 74 | "role=user bearer root" 75 | ] 76 | }, 77 | { 78 | "path": "/ResourceTypes", 79 | "name": "Allow authenticated access to ResourceTypes", 80 | "targetAttrs": "*", 81 | "rights": "read, search", 82 | "actors": [ 83 | "role=user bearer root" 84 | ] 85 | } 86 | ] 87 | } -------------------------------------------------------------------------------- /i2scim-signals/src/test/resources/schema/acis.json: -------------------------------------------------------------------------------- 1 | { 2 | "acis": [ 3 | { 4 | "path": "/", 5 | "name": "Self and employee access to read information", 6 | "targetAttrs": "*,-password", 7 | "targetFilter": "meta.resourceType eq User", 8 | "rights": "read, search, compare", 9 | "actors": [ 10 | "self", 11 | "filter=employeeNumber pr" 12 | ] 13 | }, 14 | { 15 | "path": "/", 16 | "name": "Administrators can read, search, compare all records and operational attributes", 17 | "targetAttrs": "*,+", 18 | "rights": "read, search, compare", 19 | "actors": [ 20 | "role=admin test" 21 | ] 22 | }, 23 | { 24 | "path": "/", 25 | "name": "Root can update all systems", 26 | "targetAttrs": "*,+", 27 | "rights": "add, modify, delete", 28 | "actors": [ 29 | "role=admin test" 30 | ] 31 | }, 32 | { 33 | "path": "/Users", 34 | "name": "Allow unauthenticated access to names and email addresses of Users", 35 | "targetFilter": "meta.resourceType eq User", 36 | "targetAttrs": "username,displayName,emails,name,phoneNumbers", 37 | "rights": "read, search, compare", 38 | "actors": [ 39 | "any" 40 | ] 41 | }, 42 | { 43 | "path": "/ServiceProviderConfig", 44 | "name": "Allow unauthenticated access to ServiceProviderConfig", 45 | "targetAttrs": "*", 46 | "rights": "read, search, compare", 47 | "actors": [ 48 | "any" 49 | ] 50 | }, 51 | { 52 | "path": "/Schemas", 53 | "name": "Allow unauthenticated access to ServiceProviderConfig", 54 | "targetAttrs": "*", 55 | "rights": "read, search, compare", 56 | "actors": [ 57 | "any" 58 | ] 59 | }, 60 | { 61 | "path": "/ResourceTypes", 62 | "name": "Allow unauthenticated access to ServiceProviderConfig", 63 | "targetAttrs": "*", 64 | "rights": "read, search, compare", 65 | "actors": [ 66 | "any" 67 | ] 68 | } 69 | ] 70 | } -------------------------------------------------------------------------------- /i2scim-signals/src/test/resources/scim/ReadMe.txt: -------------------------------------------------------------------------------- 1 | Temp directory for signals config storage. -------------------------------------------------------------------------------- /i2scim-tests/opa/.run/test i2scim.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /i2scim-tests/opa/opa_start.sh: -------------------------------------------------------------------------------- 1 | # docker run -v policy:/policy -p 8181:8181 openpolicyagent/opa:0.49.0-static run --server --log-level debug /policy 2 | cd opa 3 | opa run --server --log-level debug policy 4 | -------------------------------------------------------------------------------- /i2scim-tests/opa/policy/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "acis": [ 3 | { 4 | "path" : "/", 5 | "name" : "Administrators can read, search, compare all records and operational attributes", 6 | "targetAttrs" : "*", 7 | "rights" : "read, search", 8 | "actors" : [ 9 | "role=admin root" 10 | ] 11 | }, 12 | { 13 | "path" : "/", 14 | "name" : "Admins can update all resources", 15 | "targetAttrs" : "*", 16 | "rights" : "add, modify, delete", 17 | "actors" : [ 18 | "role=admin root" 19 | ] 20 | }, 21 | { 22 | "path" : "/Groups", 23 | "name" : "Allow Authenticated access to search groups", 24 | "targetAttrs" :"displayName,members", 25 | "rights" : "search", 26 | "actors" : ["role=user bearer root"] 27 | }, 28 | { 29 | "path" : "/Groups", 30 | "name" : "Allow Authenticated access read groups", 31 | "targetAttrs" :"displayName", 32 | "rights" : "read", 33 | "actors" : ["role=user bearer root"] 34 | }, 35 | { 36 | "path" : "/Users", 37 | "name" : "Allow Authenticated access to names and email addresses of Users", 38 | "targetAttrs" :"username,displayName,emails,name,phoneNumbers,ims,photos,nickName,profileUrl,title,preferredLanguage,locale,timezone", 39 | "rights" : "read, search", 40 | "actors" : ["role=user bearer root"] 41 | }, 42 | { 43 | "path" : "/Users", 44 | "name" : "Allow self read,search", 45 | "targetAttrs" :"*", 46 | "rights" : "read, search", 47 | "actors" : ["self"] 48 | }, 49 | { 50 | "path" : "/Users", 51 | "name" : "Allow self modification some personal attributes", 52 | "targetAttrs" :"username,displayName,emails,phoneNumbers,ims,photos,nickName,profileUrl,title,preferredLanguage,locale,timezone", 53 | "rights" : "modify", 54 | "actors" : ["self"] 55 | }, 56 | { 57 | "path" : "/ServiceProviderConfig", 58 | "name" : "Allow unauthenticated access to ServiceProviderConfig", 59 | "targetAttrs" :"*", 60 | "rights" : "read, search", 61 | "actors" : ["any"] 62 | }, 63 | { 64 | "path" : "/ResourceTypes", 65 | "name" : "Allow unauthenticated access to ResourceTypes", 66 | "targetAttrs" :"*", 67 | "rights" : "read, search", 68 | "actors" : ["any"] 69 | }, 70 | { 71 | "path" : "/Schemas", 72 | "name" : "Allow unauthenticated access to Schemas", 73 | "targetAttrs" :"*", 74 | "rights" : "read, search", 75 | "actors" : ["any"] 76 | } 77 | ] 78 | } -------------------------------------------------------------------------------- /i2scim-tests/opa/policy/i2scim-authz.rego: -------------------------------------------------------------------------------- 1 | package i2scim.authz 2 | 3 | import data.acis 4 | 5 | allow { 6 | count(rules) > 0 7 | } 8 | 9 | rules[rule] { 10 | some x 11 | startswith(input.path,acis[x].path) 12 | hasRight(acis[x],input.operation) 13 | isActorMatch(acis[x]) 14 | 15 | rule = acis[x] 16 | } 17 | 18 | hasRight(aci,right) { 19 | privs = split(aci.rights,", ") 20 | 21 | some i 22 | right == privs[i] 23 | } 24 | 25 | isActorMatch(aci) { 26 | some j 27 | actor = aci.actors[j] 28 | isTypeMatch(actor) 29 | } 30 | 31 | isTypeMatch(actor) { 32 | actor == "any" 33 | } 34 | 35 | isTypeMatch(actor) { 36 | actor == "self" 37 | input.path == "/Me" 38 | } 39 | 40 | isTypeMatch(actor) { 41 | # let scim evaluate 42 | startswith(actor,"ref") 43 | } 44 | 45 | isTypeMatch(actor) { 46 | # let scim evaluate 47 | startswith(actor,"filter") 48 | } 49 | 50 | isTypeMatch(actor) { 51 | startswith(actor,"role=") 52 | x := replace(actor,"role=","") 53 | vals = split(x," ") 54 | count(vals) > 0 55 | count(input.auth.roles) > 0 56 | some i,j 57 | input.auth.roles[i] == vals[j] 58 | } 59 | -------------------------------------------------------------------------------- /i2scim-tests/scimdata/resourceTypes.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "schemas" : [ "urn:ietf:params:scim:schemas:core:2.0:ResourceType" ], 3 | "id" : "ServiceProviderConfig", 4 | "name" : "ServiceProviderConfig", 5 | "endpoint" : "/ServiceProviderConfig", 6 | "description" : "Schema Discovery Endpoint", 7 | "schema" : "urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig", 8 | "meta" : { 9 | "created" : "2020-07-29T00:00:00Z", 10 | "lastModified" : "2020-07-29T00:00:00Z", 11 | "resourceType" : "ResourceType", 12 | "version" : "beta0", 13 | "location" : "/ResourceTypes/ServiceProviderConfig" 14 | } 15 | }, { 16 | "schemas" : [ "urn:ietf:params:scim:schemas:core:2.0:ResourceType" ], 17 | "id" : "ResourceType", 18 | "name" : "ResourceType", 19 | "endpoint" : "/ResourceTypes", 20 | "description" : "Resource Types Discovery Endpoint", 21 | "schema" : "urn:ietf:params:scim:schemas:core:2.0:ResourceType", 22 | "meta" : { 23 | "created" : "2020-07-29T00:00:00Z", 24 | "lastModified" : "2020-07-29T00:00:00Z", 25 | "resourceType" : "ResourceType", 26 | "version" : "beta0", 27 | "location" : "/ResourceTypes/ResourceType" 28 | } 29 | }, { 30 | "schemas" : [ "urn:ietf:params:scim:schemas:core:2.0:ResourceType" ], 31 | "id" : "Schema", 32 | "name" : "Schema", 33 | "endpoint" : "/Schemas", 34 | "description" : "Schema Discovery Endpoint", 35 | "schema" : "urn:ietf:params:scim:schemas:core:2.0:Schema", 36 | "meta" : { 37 | "created" : "2020-07-29T00:00:00Z", 38 | "lastModified" : "2020-07-29T00:00:00Z", 39 | "resourceType" : "ResourceType", 40 | "version" : "beta0", 41 | "location" : "/ResourceTypes/Schema" 42 | } 43 | }, { 44 | "schemas" : [ "urn:ietf:params:scim:schemas:core:2.0:ResourceType" ], 45 | "id" : "Group", 46 | "name" : "Group", 47 | "endpoint" : "/Groups", 48 | "description" : "Group endpoint", 49 | "schema" : "urn:ietf:params:scim:schemas:core:2.0:Group", 50 | "meta" : { 51 | "created" : "2010-01-23T04:56:22Z", 52 | "lastModified" : "2011-05-13T04:42:34Z", 53 | "resourceType" : "ResourceType", 54 | "version" : "W/\"3694e05e9dff595\"", 55 | "location" : "/ResourceTypes/Group" 56 | } 57 | }, { 58 | "schemas" : [ "urn:ietf:params:scim:schemas:core:2.0:ResourceType" ], 59 | "id" : "User", 60 | "name" : "User", 61 | "endpoint" : "/Users", 62 | "description" : "User Account", 63 | "schema" : "urn:ietf:params:scim:schemas:core:2.0:User", 64 | "schemaExtensions" : [ { 65 | "schema" : "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User", 66 | "required" : false 67 | } ], 68 | "meta" : { 69 | "created" : "2010-01-23T04:56:22Z", 70 | "lastModified" : "2011-05-13T04:42:34Z", 71 | "resourceType" : "ResourceType", 72 | "version" : "W/\"3694e05e9dff595\"", 73 | "location" : "/ResourceTypes/User" 74 | } 75 | } ] -------------------------------------------------------------------------------- /i2scim-tests/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 21 | -------------------------------------------------------------------------------- /i2scim-tests/src/main/resources/certs/jwks-certs.json: -------------------------------------------------------------------------------- 1 | {"keys":[{"kty":"RSA","kid":"i2scim","use":"Key used for i2scim testing purposes ONLY!","n":"taCP35lFs85YNnjpKqbCASaosD7QdZjGnDqWoZs93wbYHbqGRMEVQ4YInNd5MsZKcF3gGtHqo0DVM_CDiRIZxcZZuwZ3BBtRmBuQafytOCkNZKjfoOE6ptnHO9oTkyhKiNJIs-lKRldP-SDUHZ_Oux8dAnD-kJhjijInRJJkqsaO-gH26sv95O7k5S0Jm-ERr0Tqfostf0k_YM9elYXXzh7CQi3rGZ9h-ccckkcs8i-J4BVVsBDruO5Rxvtt5KVEUp0PuCrLLuqmCuhjL-JdE4EiuomdJDbAqmmQZ6Ef6g_nUH_4WcCtDtN_LerTgEzIz9D7i8NV_0Ho311R9Lt4GQ","e":"AQAB"}]} -------------------------------------------------------------------------------- /i2scim-tests/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021. Independent Identity Incorporated 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler 18 | 19 | ############################################################ 20 | # Handler specific properties. 21 | # Describes specific configuration info for Handlers. 22 | ############################################################ 23 | 24 | org.apache.juli.FileHandler.level = FINE 25 | org.apache.juli.FileHandler.directory = ${catalina.base}/logs 26 | org.apache.juli.FileHandler.prefix = ${classloader.webappName}. 27 | org.apache.juli.FileHandler.formatter = com.independentid.scim.log.JavaLogFormatter 28 | 29 | 30 | java.util.logging.ConsoleHandler.level = FINE 31 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -------------------------------------------------------------------------------- /i2scim-tests/src/main/resources/resources-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources": [ 3 | { 4 | "pattern": ".*\\.json$" 5 | } 6 | ] 7 | } -------------------------------------------------------------------------------- /i2scim-tests/src/main/resources/schema/acis.json: -------------------------------------------------------------------------------- 1 | { 2 | "acis": [ 3 | { 4 | "path" : "/", 5 | "name" : "Self and employee access to read information", 6 | "targetAttrs" : "*,-password", 7 | "targetFilter" : "meta.resourceType eq User", 8 | "rights" : "read, search, compare", 9 | "actors" : ["self", "filter=employeeNumber pr"] 10 | }, 11 | 12 | { 13 | "path" : "/", 14 | "name" : "Administrators can read, search, compare all records and operational attributes", 15 | "targetAttrs" : "*", 16 | "rights" : "read, search, compare", 17 | "actors" : [ 18 | "role=admin root" 19 | ] 20 | }, 21 | { 22 | "path" : "/", 23 | "name" : "Admins can update all resources", 24 | "targetAttrs" : "*", 25 | "rights" : "add, modify, delete", 26 | "actors" : [ 27 | "role=admin root" 28 | ] 29 | }, 30 | 31 | { 32 | "path" : "/Users", 33 | "name" : "Allow unauthenticated access to names and email addresses of Users", 34 | "targetFilter":"meta.resourceType eq User", 35 | "targetAttrs" :"username,displayName,emails,name,phoneNumbers", 36 | "rights" : "read, search, compare", 37 | "actors" : ["any"] 38 | }, 39 | 40 | { 41 | "path" : "/ServiceProviderConfig", 42 | "name" : "Allow unauthenticated access to ServiceProviderConfig", 43 | "targetAttrs" :"*", 44 | "rights" : "read, search, compare", 45 | "actors" : ["any"] 46 | }, 47 | 48 | { 49 | "path" : "/ResourceTypes", 50 | "name" : "Allow unauthenticated access to ResourceTypes", 51 | "targetAttrs" :"*", 52 | "rights" : "read, search, compare", 53 | "actors" : ["any"] 54 | }, 55 | { 56 | "path" : "/Schemas", 57 | "name" : "Allow unauthenticated access to Schemas", 58 | "targetAttrs" :"*", 59 | "rights" : "read, search, compare", 60 | "actors" : ["any"] 61 | } 62 | ] 63 | } -------------------------------------------------------------------------------- /i2scim-tests/src/test/java/com/independentid/scim/test/auth/ScimAuthTestProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.test.auth; 18 | 19 | import com.independentid.scim.backend.mongo.MongoProvider; 20 | import com.independentid.scim.test.misc.TestUtils; 21 | import io.quarkus.test.junit.QuarkusTestProfile; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | public class ScimAuthTestProfile implements QuarkusTestProfile { 27 | 28 | @Override 29 | public Map getConfigOverrides() { 30 | Map cmap = new HashMap<>(Map.of( 31 | "scim.prov.providerClass", MongoProvider.class.getName(), 32 | "scim.prov.mongo.test", "true", 33 | "scim.prov.mongo.dbname", "secTestSCIM", 34 | 35 | "scim.security.enable", "true", 36 | 37 | "quarkus.http.test-port", "0", 38 | "quarkus.log.level","INFO", 39 | "logging.level.com.independentid.scim","INFO", 40 | "quarkus.log.category.\"com.independentid.scim.test\".level", "INFO", 41 | 42 | "scim.security.acis","classpath:/schema/aciSecurityTest.json" 43 | )); 44 | cmap.putAll(Map.of( 45 | "quarkus.http.auth.basic", "true", 46 | "scim.security.authen.basic", "true", 47 | 48 | "scim.event.enable","false", 49 | "scim.root.dir","." //enables local debug testing 50 | )); 51 | 52 | cmap.putAll(Map.of( 53 | "scim.security.authen.jwt", "true", 54 | "mp.jwt.verify.publickey.location",TestUtils.VALIDATE_KEY, 55 | "smallrye.jwt.always-check-authorization","true", 56 | "mp.jwt.verify.issuer","test.i2scim.io", 57 | "mp.jwt.verify.audience","aud.test.i2scim.io" 58 | )); 59 | 60 | TestUtils.configTestEndpointsMap(cmap); 61 | return cmap; 62 | 63 | 64 | } 65 | 66 | @Override 67 | public String getConfigProfile() { 68 | return "ScimAuthenTestProfile"; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /i2scim-tests/src/test/java/com/independentid/scim/test/devops/ScimDevOpsTestProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.test.devops; 18 | 19 | import com.independentid.scim.backend.memory.MemoryProvider; 20 | import com.independentid.scim.backend.mongo.MongoProvider; 21 | import com.independentid.scim.test.misc.TestUtils; 22 | import io.quarkus.test.junit.QuarkusTestProfile; 23 | 24 | import java.util.HashMap; 25 | import java.util.Map; 26 | 27 | public class ScimDevOpsTestProfile implements QuarkusTestProfile { 28 | @Override 29 | public Map getConfigOverrides() { 30 | 31 | 32 | Map cmap = new HashMap<>(Map.of( 33 | "scim.prov.providerClass", MongoProvider.class.getName(), 34 | "quarkus.http.test-port", "0", 35 | "quarkus.log.min-level","DEBUG", 36 | "quarkus.log.category.\"com.independentid.scim.test\".level", "INFO", 37 | 38 | "scim.event.enable","false", 39 | "scim.root.dir",".", //enables local debug testing 40 | 41 | "scim.security.enable", "true", 42 | "scim.security.authen.basic", "true", 43 | "scim.security.acis","classpath:/schema/aciSecurityTest.json" 44 | )); 45 | 46 | cmap.putAll(Map.of( 47 | "scim.security.authen.jwt", "true", 48 | "mp.jwt.verify.publickey.location",TestUtils.VALIDATE_KEY, 49 | "smallrye.jwt.always-check-authorization","true", 50 | "mp.jwt.verify.issuer","test.i2scim.io", 51 | "mp.jwt.verify.audience","aud.test.i2scim.io" 52 | )); 53 | 54 | TestUtils.configTestEndpointsMap(cmap); 55 | cmap.put("scim.prov.mongo.dbname", "opsTestSCIM"); 56 | 57 | return cmap; 58 | 59 | 60 | } 61 | 62 | @Override 63 | public String getConfigProfile() { 64 | return "ScimDevOpsTestProfile"; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /i2scim-tests/src/test/java/com/independentid/scim/test/http/ScimHttpTestProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.test.http; 18 | 19 | import com.independentid.scim.backend.memory.MemoryProvider; 20 | import io.quarkus.test.junit.QuarkusTestProfile; 21 | 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | public class ScimHttpTestProfile implements QuarkusTestProfile { 26 | @Override 27 | public Map getConfigOverrides() { 28 | Map cmap = new HashMap<>(Map.of( 29 | "scim.schema.path","/schema/scimSchemaTest.json", //this test schema changes some default returns for testing 30 | 31 | "scim.prov.providerClass", MemoryProvider.class.getName(), 32 | "scim.prov.memory.maxbackups", "2", 33 | "scim.prov.memory.backup.mins","5", 34 | 35 | "quarkus.http.test-port","0", 36 | "quarkus.log.min-level","DEBUG", 37 | "logging.level.com.independentid.scim","INFO", 38 | "quarkus.log.category.\"com.independentid.scim.test\".level","INFO" 39 | )); 40 | cmap.putAll(Map.of( 41 | "scim.json.pretty","true", 42 | "scim.security.enable", "false", 43 | "scim.event.enable","false", 44 | "scim.root.dir","." //enables local debug testing 45 | )); 46 | return cmap; 47 | } 48 | 49 | @Override 50 | public String getConfigProfile() { 51 | return "ScimHttpTestProfile"; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /i2scim-tests/src/test/java/com/independentid/scim/test/memory/ScimMemoryTestProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.test.memory; 18 | 19 | import com.independentid.scim.backend.memory.MemoryProvider; 20 | import io.quarkus.test.junit.QuarkusTestProfile; 21 | 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | public class ScimMemoryTestProfile implements QuarkusTestProfile { 26 | @Override 27 | public Map getConfigOverrides() { 28 | Map cmap = new HashMap<>( Map.of( 29 | "scim.schema.path","classpath:/schema/scimSchemaTest.json", 30 | 31 | "scim.prov.providerClass", MemoryProvider.class.getName(), 32 | "scim.prov.memory.maxbackups", "2", 33 | "scim.prov.memory.backup.mins","1", 34 | 35 | "quarkus.http.test-port","0", 36 | "quarkus.log.min-level","DEBUG", 37 | "logging.level.com.independentid.scim","INFO", 38 | "quarkus.log.category.\"com.independentid.scim.test\".level","INFO" 39 | )); 40 | cmap.putAll(Map.of( 41 | "scim.security.enable", "false", 42 | "scim.event.enable","false", 43 | "scim.root.dir","." //enables local debug testing 44 | 45 | )); 46 | return cmap; 47 | } 48 | 49 | @Override 50 | public String getConfigProfile() { 51 | return "ScimMemoryTestProfile"; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /i2scim-tests/src/test/java/com/independentid/scim/test/mongo/MongoTests.md: -------------------------------------------------------------------------------- 1 | ## Mongo Setup and Testing Notes 2 | 3 | For testing a mongo server is normally setup on the local host. 4 | 5 | Set up an account and enable access control. See [Mongodb: Enable Access Control](https://docs.mongodb.com/manual/tutorial/enable-authentication/). 6 | 7 | If the username/password is to be changed, the appropriate settings in ScimMongoTestProfile must also be changed. 8 | 9 | In Mongo admin: 10 | 11 | ` 12 | db.createUser({user:"admin",pwd:"t0p-Secret",roles:[{role:"userAdminAnyDatabase",db:"admin"},"readWriteAnyDatabase", 13 | "dbAdminAnyDatabase"]}) 14 | ` 15 | 16 | Deploying on MacOS: [Installing MongoDB Community Edition on macOS](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/) -------------------------------------------------------------------------------- /i2scim-tests/src/test/java/com/independentid/scim/test/mongo/ScimMongoTestProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.test.mongo; 18 | 19 | import com.independentid.scim.backend.mongo.MongoProvider; 20 | import com.independentid.scim.test.misc.TestUtils; 21 | import io.quarkus.test.junit.QuarkusTestProfile; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | public class ScimMongoTestProfile implements QuarkusTestProfile { 27 | @Override 28 | public Map getConfigOverrides() { 29 | 30 | Map cmap = new HashMap<>( Map.of( 31 | "scim.prov.providerClass", MongoProvider.class.getName(), 32 | "scim.prov.mongo.dbname", "mongoTestSCIM", 33 | "scim.schema.path","classpath:/schema/scimSchemaTest.json", 34 | "quarkus.http.test-port","0", 35 | "quarkus.log.min-level","DEBUG", 36 | "logging.level.com.independentid.scim","INFO", 37 | "quarkus.log.category.\"com.independentid.scim.test\".level","INFO", 38 | 39 | "scim.security.enable", "false", 40 | "scim.event.enable","false", 41 | "scim.root.dir","." 42 | )); 43 | // cmap.put("scim.prov.mongo.uri","mongodb://localhost:27117"); 44 | TestUtils.configTestEndpointsMap(cmap); 45 | return cmap; 46 | } 47 | 48 | @Override 49 | public String getConfigProfile() { 50 | return "ScimMongoTestProfile"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /i2scim-tests/src/test/java/com/independentid/scim/test/opa/OpaTestProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.test.opa; 18 | 19 | import com.independentid.scim.backend.memory.MemoryProvider; 20 | import com.independentid.scim.backend.mongo.MongoProvider; 21 | import com.independentid.scim.filter.OpaSecurityFilter; 22 | import com.independentid.scim.test.misc.TestUtils; 23 | import io.quarkus.test.junit.QuarkusTestProfile; 24 | 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | 28 | public class OpaTestProfile implements QuarkusTestProfile { 29 | @Override 30 | public Map getConfigOverrides() { 31 | String env_opa_uri = System.getenv("TEST_OPA_URL"); 32 | if (env_opa_uri == null) 33 | env_opa_uri = "http://localhost:8181/v1/data/i2scim"; 34 | 35 | 36 | Map cmap = new HashMap<>(Map.of( 37 | "scim.prov.providerClass", MemoryProvider.class.getName(), 38 | "scim.prov.memory.maxbackups", "2", 39 | "scim.prov.memory.backup.mins","5", 40 | 41 | "quarkus.http.test-port", "0", 42 | "quarkus.log.level","INFO", 43 | "logging.level.com.independentid.scim","DEBUG", 44 | "quarkus.log.category.\"com.independentid.scim.test\".level", "DEBUG" 45 | 46 | )); 47 | cmap.putAll(Map.of( 48 | "quarkus.http.auth.basic", "true", 49 | "scim.security.enable", "true", 50 | "scim.security.authen.basic", "true", 51 | "scim.security.authen.jwt", "true", 52 | "scim.security.acis","classpath:/schema/aciSecurityTest.json", 53 | 54 | "scim.event.enable","false", 55 | "scim.root.dir","." , 56 | "scim.security.mode", OpaSecurityFilter.ACCESS_TYPE_OPA, //enables local debug testing 57 | "scim.opa.authz.url", env_opa_uri 58 | )); 59 | TestUtils.configTestEndpointsMap(cmap); 60 | // cmap.put("scim.prov.mongo.uri","mongodb://localhost:27117"); 61 | return cmap; 62 | 63 | 64 | } 65 | 66 | @Override 67 | public String getConfigProfile() { 68 | return "ScimAuthenTestProfile"; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /i2scim-tests/src/test/java/com/independentid/scim/test/sub/JacksonTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.test.sub; 18 | 19 | import com.fasterxml.jackson.databind.node.ArrayNode; 20 | import com.fasterxml.jackson.databind.node.ObjectNode; 21 | import com.independentid.scim.schema.Schema; 22 | import com.independentid.scim.serializer.JsonUtil; 23 | import io.quarkus.test.junit.QuarkusTest; 24 | import io.quarkus.test.junit.TestProfile; 25 | import org.junit.jupiter.api.Test; 26 | 27 | @QuarkusTest 28 | @TestProfile(ScimSubComponentTestProfile.class) 29 | public class JacksonTest { 30 | 31 | @Test 32 | public void aTest() { 33 | ObjectNode node = getNode(); 34 | System.out.println("Basic Node:\n"+node.toPrettyString()); 35 | String nstring = node.toString(); 36 | System.out.println("Compare string:\n"+nstring); 37 | 38 | node.set("objtest",getObj(1)); 39 | 40 | System.out.println("Nested obj:\n"+node.toPrettyString()); 41 | 42 | node = getNode(); 43 | node.setAll(getObj(2)); 44 | 45 | System.out.println("Setall:\n"+node.toPrettyString()); 46 | 47 | ArrayNode anode = node.putArray("testArray"); 48 | for (int i=1; i<10; i++) { 49 | anode.add(getObj(i)); 50 | } 51 | 52 | System.out.println("Array:\n"+node.toPrettyString()); 53 | } 54 | 55 | public ObjectNode getNode() { 56 | ObjectNode node = JsonUtil.getMapper().createObjectNode(); 57 | 58 | node.putArray("schemas").add(Schema.SCHEMA_ID); 59 | node.put("id","bleh"); 60 | return node; 61 | } 62 | 63 | public ObjectNode getObj(int val) { 64 | ObjectNode node = JsonUtil.getMapper().createObjectNode(); 65 | node.put("attribute",val); 66 | return node; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /i2scim-tests/src/test/java/com/independentid/scim/test/sub/ScimSubComponentTestProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.test.sub; 18 | 19 | import com.independentid.scim.backend.memory.MemoryProvider; 20 | import io.quarkus.test.junit.QuarkusTestProfile; 21 | 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | public class ScimSubComponentTestProfile implements QuarkusTestProfile { 26 | @Override 27 | public Map getConfigOverrides() { 28 | Map cmap = new HashMap<>( Map.of( 29 | "scim.schema.path","/schema/scimSchemaTest.json", 30 | "scim.test.configOnly","true", 31 | "scim.json.pretty","true", 32 | 33 | "quarkus.log.min-level","DEBUG", 34 | "logging.level.com.independentid.scim","INFO", 35 | "quarkus.log.category.\"com.independentid.scim.test\".level","INFO", 36 | 37 | "scim.prov.providerClass", MemoryProvider.class.getName(), 38 | "scim.prov.persist.schema","false", 39 | "scim.security.enable", "false", 40 | "scim.event.enable","false" 41 | )); 42 | cmap.put("scim.root.dir","."); 43 | cmap.put("scim.kafka.log.enable","false"); //enables local debug testing 44 | return cmap; 45 | } 46 | 47 | @Override 48 | public String getConfigProfile() { 49 | return "ScimSubComponentConfigTestProfile"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /i2scim-tests/src/test/resources/certs/jwks-certs.json: -------------------------------------------------------------------------------- 1 | {"keys":[{"kty":"RSA","kid":"i2scim","use":"Key used for i2scim testing purposes ONLY!","n":"taCP35lFs85YNnjpKqbCASaosD7QdZjGnDqWoZs93wbYHbqGRMEVQ4YInNd5MsZKcF3gGtHqo0DVM_CDiRIZxcZZuwZ3BBtRmBuQafytOCkNZKjfoOE6ptnHO9oTkyhKiNJIs-lKRldP-SDUHZ_Oux8dAnD-kJhjijInRJJkqsaO-gH26sv95O7k5S0Jm-ERr0Tqfostf0k_YM9elYXXzh7CQi3rGZ9h-ccckkcs8i-J4BVVsBDruO5Rxvtt5KVEUp0PuCrLLuqmCuhjL-JdE4EiuomdJDbAqmmQZ6Ef6g_nUH_4WcCtDtN_LerTgEzIz9D7i8NV_0Ho311R9Lt4GQ","e":"AQAB"}]} -------------------------------------------------------------------------------- /i2scim-tests/src/test/resources/schema/aciSecurityTest.json: -------------------------------------------------------------------------------- 1 | { 2 | "acis": [ 3 | 4 | { 5 | "path" : "/", 6 | "name" : "Administrators can read, search, compare all records and operational attributes", 7 | "targetAttrs" : "*", 8 | "rights" : "read, search, compare", 9 | "actors" : [ 10 | "role=root admin full" 11 | ] 12 | }, 13 | { 14 | "path" : "/", 15 | "name" : "Root can update all systems", 16 | "targetAttrs" : "*", 17 | "rights" : "add, modify, delete", 18 | "actors" : [ 19 | "role=root admin full" 20 | ] 21 | }, 22 | 23 | { 24 | "path" : "/Users", 25 | "name" : "Users can read self except userType", 26 | "targetAttrs": "*,-userType,-ims", 27 | "rights" : "read,search", 28 | "actors" : [ "self"] 29 | }, 30 | { 31 | "path" : "/Users", 32 | "name" : "Users can self-modify some attributes", 33 | "targetAttrs": "displayName, emails, nickName, addresses, phoneNumbers", 34 | "rights" : "modify", 35 | "actors" : [ "self"] 36 | }, 37 | 38 | { 39 | "path" : "/Users", 40 | "name" : "Allow unauthenticated access to names and email addresses of Users", 41 | "targetFilter":"meta.resourceType eq User", 42 | "targetAttrs" :"username,displayName,emails,name,phoneNumbers", 43 | "rights" : "read", 44 | "actors" : ["role=user bearer root"] 45 | }, 46 | { 47 | "path" : "/Users", 48 | "name" : "Allow unauthenticated access to names and email addresses of Users", 49 | "targetFilter":"meta.resourceType eq User", 50 | "targetAttrs" :"username", 51 | "rights" : "search", 52 | "actors" : ["role=user bearer root"] 53 | }, 54 | 55 | { 56 | "path" : "/ServiceProviderConfig", 57 | "name" : "Allow unauthenticated access to ServiceProviderConfig", 58 | "targetAttrs" :"*", 59 | "rights" : "read, search", 60 | "actors" : ["any"] 61 | }, 62 | { 63 | "path" : "/Schemas", 64 | "name" : "Allow authenticated access to Schemas", 65 | "targetAttrs" :"*", 66 | "rights" : "read, search", 67 | "actors" : ["role=user bearer root"] 68 | }, 69 | { 70 | "path" : "/ResourceTypes", 71 | "name" : "Allow authenticated access to ResourceTypes", 72 | "targetAttrs" :"*", 73 | "rights" : "read, search", 74 | "actors" : ["role=user bearer root"] 75 | } 76 | ] 77 | } -------------------------------------------------------------------------------- /i2scim-tests/src/test/resources/schema/acis.json: -------------------------------------------------------------------------------- 1 | { 2 | "acis": [ 3 | { 4 | "path" : "/", 5 | "name" : "Self and employee access to read information", 6 | "targetAttrs" : "*,-password", 7 | "targetFilter" : "meta.resourceType eq User", 8 | "rights" : "read, search, compare", 9 | "actors" : ["self", "filter=employeeNumber pr"] 10 | }, 11 | 12 | { 13 | "path" : "/", 14 | "name" : "Administrators can read, search, compare all records and operational attributes", 15 | "targetAttrs" : "*,+", 16 | "rights" : "read, search, compare", 17 | "actors" : [ 18 | "role=admin test" 19 | ] 20 | }, 21 | { 22 | "path" : "/", 23 | "name" : "Root can update all systems", 24 | "targetAttrs" : "*,+", 25 | "rights" : "add, modify, delete", 26 | "actors" : [ 27 | "role=admin test" 28 | ] 29 | }, 30 | 31 | { 32 | "path" : "/Users", 33 | "name" : "Allow unauthenticated access to names and email addresses of Users", 34 | "targetFilter":"meta.resourceType eq User", 35 | "targetAttrs" :"username,displayName,emails,name,phoneNumbers", 36 | "rights" : "read, search, compare", 37 | "actors" : ["any"] 38 | }, 39 | 40 | { 41 | "path" : "/ServiceProviderConfig", 42 | "name" : "Allow unauthenticated access to ServiceProviderConfig", 43 | "targetAttrs" :"*", 44 | "rights" : "read, search, compare", 45 | "actors" : ["any"] 46 | }, 47 | { 48 | "path" : "/Schemas", 49 | "name" : "Allow unauthenticated access to ServiceProviderConfig", 50 | "targetAttrs" :"*", 51 | "rights" : "read, search, compare", 52 | "actors" : ["any"] 53 | }, 54 | { 55 | "path" : "/ResourceTypes", 56 | "name" : "Allow unauthenticated access to ServiceProviderConfig", 57 | "targetAttrs" :"*", 58 | "rights" : "read, search, compare", 59 | "actors" : ["any"] 60 | } 61 | ] 62 | } -------------------------------------------------------------------------------- /i2scim-universal/1-i2scim-memory-configs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: scim-mem 5 | --- 6 | apiVersion: v1 7 | kind: Secret 8 | metadata: 9 | name: i2scim-root 10 | namespace: scim-mem 11 | type: Opaque 12 | data: 13 | #Base64 encoded values 14 | scim.security.root.username: YWRtaW4= 15 | scim.security.root.password: YWRtaW4= 16 | --- 17 | apiVersion: v1 18 | kind: ConfigMap 19 | metadata: 20 | namespace: scim-mem 21 | name: i2scim-mem-config 22 | data: 23 | scim.event.enable: "false" 24 | scim.prov.providerClass: com.independentid.scim.backend.memory.MemoryProvider 25 | scim.prov.memory.dir: "/scim/data" 26 | scim.prov.memory.file: "scimdb.json" 27 | scim.prov.memory.maxbackups: "10" 28 | scim.prov.memory.backup.mins: "60" 29 | # Indicates the attributes to be indexed 30 | scim.prov.memory.indexes: User:userName,User:emails.value,Group:displayName 31 | 32 | scim.resourcetype.path: "/config/resourceTypes.json" 33 | scim.schema.path: "/config/scimSchema.json" 34 | 35 | # Security Configuration 36 | scim.security.enable: "true" 37 | # Locations of the acis.json file to use 38 | scim.security.acis: "/config/acis.json" 39 | scim.security.root.enable: "true" 40 | # When basic is enabled, i2scim will attempt to process HTTP Basic Auth against User resources 41 | # located in the Memory provider database. 42 | scim.security.authen.basic: "true" 43 | 44 | # Configuration for JWT authentication 45 | scim.security.authen.jwt: "false" 46 | 47 | # The JWT claim used to match RBAC scopes used in acis processing 48 | scim.security.authen.jwt.claim.scope: "scope" 49 | 50 | # See: Quarkus Using JWT RBAC for configuration details 51 | # https://quarkus.io/guides/security-jwt 52 | quarkus.smallrye-jwt.enabled: "true" 53 | smallrye.jwt.always-check-authorization: "true" 54 | mp.jwt.verify.issuer: "test.i2scim.io" 55 | mp.jwt.verify.audiences: "aud.test.i2scim.io" 56 | #mp.jwt.verify.location: "https://example.com/jwkset.json" 57 | mp.jwt.verify.publickey: "eyJrZXlzIjpbeyJrdHkiOiJSU0EiLCJraWQiOiJpMnNjaW0iLCJ1c2UiOiJLZXkgdXNlZCBmb3Ig 58 | aTJzY2ltIHRlc3RpbmcgcHVycG9zZXMgT05MWSEiLCJuIjoidGFDUDM1bEZzODVZTm5qcEtxYkNB 59 | U2Fvc0Q3UWRaakduRHFXb1pzOTN3YllIYnFHUk1FVlE0WUluTmQ1TXNaS2NGM2dHdEhxbzBEVk1f 60 | Q0RpUklaeGNaWnV3WjNCQnRSbUJ1UWFmeXRPQ2tOWktqZm9PRTZwdG5ITzlvVGt5aEtpTkpJcy1s 61 | S1JsZFAtU0RVSFpfT3V4OGRBbkQta0poamlqSW5SSkprcXNhTy1nSDI2c3Y5NU83azVTMEptLUVS 62 | cjBUcWZvc3RmMGtfWU05ZWxZWFh6aDdDUWkzckdaOWgtY2Nja2tjczhpLUo0QlZWc0JEcnVPNVJ4 63 | dnR0NUtWRVVwMFB1Q3JMTHVxbUN1aGpMLUpkRTRFaXVvbWRKRGJBcW1tUVo2RWY2Z19uVUhfNFdj 64 | Q3REdE5fTGVyVGdFekl6OUQ3aThOVl8wSG8zMTFSOUx0NEdRIiwiZSI6IkFRQUIifV19" 65 | --- -------------------------------------------------------------------------------- /i2scim-universal/2-i2scim-gke-memory-pvset.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Persistent Volume Claim for Google Cloud using GKE 3 | # 4 | apiVersion: v1 5 | kind: PersistentVolumeClaim 6 | metadata: 7 | namespace: scim-mem 8 | name: i2scim-pvc 9 | spec: 10 | storageClassName: premium-rwo 11 | accessModes: 12 | - ReadWriteOnce 13 | resources: 14 | requests: 15 | storage: 5Gi 16 | --- 17 | 18 | -------------------------------------------------------------------------------- /i2scim-universal/2-i2scim-memory-pvset.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # PV and PVC set for running on NFS volume (e.g. on bare metal cluster) 3 | # 4 | apiVersion: v1 5 | kind: PersistentVolume 6 | metadata: 7 | name: i2scim-pv1 8 | namespace: scim-mem 9 | labels: 10 | app: i2scim 11 | spec: 12 | capacity: 13 | storage: 50Gi 14 | volumeMode: Filesystem 15 | accessModes: [ ReadWriteOnce ] 16 | persistentVolumeReclaimPolicy: Retain 17 | storageClassName: nfs 18 | mountOptions: 19 | - hard 20 | - nfsvers=4.1 21 | nfs: 22 | path: /nfs/data/i2scim-pv/rep1 23 | server: 10.1.10.110 24 | readOnly: false 25 | --- 26 | apiVersion: v1 27 | kind: PersistentVolume 28 | metadata: 29 | name: i2scim-pv2 30 | namespace: scim-mem 31 | labels: 32 | app: i2scim 33 | spec: 34 | capacity: 35 | storage: 50Gi 36 | volumeMode: Filesystem 37 | accessModes: [ ReadWriteOnce ] 38 | persistentVolumeReclaimPolicy: Retain 39 | storageClassName: nfs 40 | mountOptions: 41 | - hard 42 | - nfsvers=4.1 43 | nfs: 44 | path: /nfs/data/i2scim-pv/rep2 45 | server: 10.1.10.110 46 | readOnly: false 47 | --- 48 | apiVersion: v1 49 | kind: PersistentVolume 50 | metadata: 51 | name: i2scim-pv3 52 | namespace: scim-mem 53 | labels: 54 | app: i2scim 55 | spec: 56 | capacity: 57 | storage: 50Gi 58 | volumeMode: Filesystem 59 | accessModes: [ ReadWriteOnce ] 60 | persistentVolumeReclaimPolicy: Retain 61 | storageClassName: nfs 62 | mountOptions: 63 | - hard 64 | - nfsvers=4.1 65 | nfs: 66 | path: /nfs/data/i2scim-pv/rep3 67 | server: 10.1.10.110 68 | readOnly: false 69 | --- 70 | apiVersion: v1 71 | kind: PersistentVolumeClaim 72 | metadata: 73 | namespace: scim-mem 74 | name: i2scim-pvc 75 | spec: 76 | accessModes: 77 | - ReadWriteOnce 78 | storageClassName: nfs 79 | resources: 80 | requests: 81 | storage: 5Gi 82 | selector: 83 | matchLabels: 84 | app: i2scim 85 | --- 86 | 87 | -------------------------------------------------------------------------------- /i2scim-universal/deploy-instructions.md: -------------------------------------------------------------------------------- 1 | ## i2scim Using Memory Provider 2 | 3 | This packaging of i2scim deploys using the memory provider. Active information is stored in-memory for fast updates 4 | and queries. The memory provider persists data to disk on a scheduled cycle determined by configuration. 5 | 6 | Notice: This package is designed to be a demonstration for testing purposes of the implementation of SCIM protocol. 7 | This configuration does not include replication or multi-server support. A future enhancement will be made available 8 | separately to provide replication services based on Apache Kafka. For more information contact [info@independentid. 9 | com](mailto:info@independentid.com). 10 | 11 | ### Kubernetes Deployments 12 | 13 | To deploy i2scim in Kubernetes, 4 files are provided as templates as follows: 14 | 15 | * `1-i2scim-memory-configs.yaml` Defines the basic environment settings for the i2scim server. 16 | This includes defining secrets such as the root account for the server. 17 | 18 | * Persistent volume set definitions: 19 | - `2-i2scim-memory-pvset.yaml` defines the persistent volume sets and claims for the 20 | i2scim server using NFS (e.g. on bare metal cluster). 21 | - `2-i2scim-gke-memory-pvset.yaml` defines a persistent volume 22 | claim for Google Cloud. 23 | 24 | Modify these files as needed to create your kubernetes persistent volumes. These volumes will be used by i2sciim to 25 | persist SCIM data. Set the volume size to match the expected data set size. 26 | 27 | * `3-i2scim-config-schema.yaml` Defines the data model and access control the server will provide. i2scim works by 28 | automatically loading schema definitions and resource types at run time. Modify these configmaps to change the data 29 | model and access control for the server as follows: 30 | - `acis.json` The access control policy for the server. See [Access Control](../AccessControl.md) for information 31 | on the format of this file. 32 | - `resourceTypes.json` The ResourceTypes defined in this server. This file corresponds to 33 | [RFC7643 Section 6](https://datatracker.ietf.org/doc/html/rfc7643#section-6) 34 | and [RFC7644 Section 4](https://datatracker.ietf.org/doc/html/rfc7644#section-4) 35 | defining configuration discovery. 36 | - `scimCommonSchema.json` This file defines the common attributes used in all resource types in the server. **This 37 | file should not be changed as implementation is fixed.** 38 | - -------------------------------------------------------------------------------- /i2scim-universal/scim/ReadMe.txt: -------------------------------------------------------------------------------- 1 | # This directory is used to become the root directory for the SCIM server on Docker. -------------------------------------------------------------------------------- /i2scim-universal/src/main/docker/Dockerfile.native: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package -Pnative 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/i2scim-parent . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/i2scim-parent 15 | # 16 | ### 17 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.6 18 | WORKDIR /work/ 19 | RUN chown 1001 /work \ 20 | && chmod "g+rwX" /work \ 21 | && chown 1001:root /work 22 | COPY --chown=1001:root target/*-runner /work/application 23 | 24 | RUN mkdir /scim && chown 185 /scim 25 | 26 | EXPOSE 8080 27 | USER 1001 28 | 29 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] 30 | -------------------------------------------------------------------------------- /i2scim-universal/src/main/docker/Dockerfile.native-micro: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # It uses a micro base image, tuned for Quarkus native executables. 4 | # It reduces the size of the resulting container image. 5 | # Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. 6 | # 7 | # Before building the container image run: 8 | # 9 | # ./mvnw package -Pnative 10 | # 11 | # Then, build the image with: 12 | # 13 | # docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/i2scim-parent . 14 | # 15 | # Then run the container using: 16 | # 17 | # docker run -i --rm -p 8080:8080 quarkus/i2scim-parent 18 | # 19 | ### 20 | FROM quay.io/quarkus/quarkus-micro-image:2.0 21 | WORKDIR /work/ 22 | RUN chown 1001 /work \ 23 | && chmod "g+rwX" /work \ 24 | && chown 1001:root /work 25 | COPY --chown=1001:root target/*-runner /work/application 26 | 27 | RUN mkdir /scim && chown 1001 /scim 28 | 29 | EXPOSE 8080 30 | USER 1001 31 | 32 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] 33 | -------------------------------------------------------------------------------- /i2scim-universal/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 21 | -------------------------------------------------------------------------------- /i2scim-universal/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021. Independent Identity Incorporated 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | handlers=org.apache.juli.FileHandler, java.util.logging.ConsoleHandler 17 | ############################################################ 18 | # Handler specific properties. 19 | # Describes specific configuration info for Handlers. 20 | ############################################################ 21 | org.apache.juli.FileHandler.level=FINE 22 | org.apache.juli.FileHandler.directory=${catalina.base}/logs 23 | org.apache.juli.FileHandler.prefix=${classloader.webappName}. 24 | org.apache.juli.FileHandler.formatter=com.independentid.scim.log.JavaLogFormatter 25 | java.util.logging.ConsoleHandler.level=FINE 26 | java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter -------------------------------------------------------------------------------- /i2scim-universal/src/main/resources/resources-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources": [ 3 | { 4 | "pattern": ".*\\.json$" 5 | } 6 | ] 7 | } -------------------------------------------------------------------------------- /i2scim-universal/src/main/resources/schema/acis.json: -------------------------------------------------------------------------------- 1 | { 2 | "acis": [ 3 | { 4 | "path": "/", 5 | "name": "Administrators can read, search, compare all records and operational attributes", 6 | "targetAttrs": "*", 7 | "rights": "read, search", 8 | "actors": [ 9 | "role=admin root" 10 | ] 11 | }, 12 | { 13 | "path": "/", 14 | "name": "Admins can update all resources", 15 | "targetAttrs": "*", 16 | "rights": "add, modify, delete", 17 | "actors": [ 18 | "role=admin root" 19 | ] 20 | }, 21 | { 22 | "path": "/Groups", 23 | "name": "Allow Authenticated access to search groups", 24 | "targetAttrs": "displayName,members", 25 | "rights": "search", 26 | "actors": [ 27 | "role=user bearer root" 28 | ] 29 | }, 30 | { 31 | "path": "/Groups", 32 | "name": "Allow Authenticated access read groups", 33 | "targetAttrs": "displayName", 34 | "rights": "read", 35 | "actors": [ 36 | "role=user bearer root" 37 | ] 38 | }, 39 | { 40 | "path": "/Users", 41 | "name": "Allow Authenticated access to names and email addresses of Users", 42 | "targetAttrs": "username,displayName,emails,name,phoneNumbers,ims,photos,nickName,profileUrl,title,preferredLanguage,locale,timezone", 43 | "rights": "read, search", 44 | "actors": [ 45 | "role=user bearer root" 46 | ] 47 | }, 48 | { 49 | "path": "/Users", 50 | "name": "Allow self read,search", 51 | "targetAttrs": "*", 52 | "rights": "read, search", 53 | "actors": [ 54 | "self" 55 | ] 56 | }, 57 | { 58 | "path": "/Users", 59 | "name": "Allow self modification some personal attributes", 60 | "targetAttrs": "username,displayName,emails,phoneNumbers,ims,photos,nickName,profileUrl,title,preferredLanguage,locale,timezone", 61 | "rights": "modify", 62 | "actors": [ 63 | "self" 64 | ] 65 | }, 66 | { 67 | "path": "/ServiceProviderConfig", 68 | "name": "Allow unauthenticated access to ServiceProviderConfig", 69 | "targetAttrs": "*", 70 | "rights": "read, search", 71 | "actors": [ 72 | "any" 73 | ] 74 | }, 75 | { 76 | "path": "/ResourceTypes", 77 | "name": "Allow unauthenticated access to ResourceTypes", 78 | "targetAttrs": "*", 79 | "rights": "read, search", 80 | "actors": [ 81 | "any" 82 | ] 83 | }, 84 | { 85 | "path": "/Schemas", 86 | "name": "Allow unauthenticated access to Schemas", 87 | "targetAttrs": "*", 88 | "rights": "read, search", 89 | "actors": [ 90 | "any" 91 | ] 92 | } 93 | ] 94 | } -------------------------------------------------------------------------------- /opa/opa_start.sh: -------------------------------------------------------------------------------- 1 | # docker run -v policy:/policy -p 8181:8181 openpolicyagent/opa:0.49.0-static run --server --log-level debug /policy 2 | opa run --server --log-level debug policy 3 | -------------------------------------------------------------------------------- /opa/policy/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "acis": [ 3 | { 4 | "path" : "/", 5 | "name" : "Administrators can read, search, compare all records and operational attributes", 6 | "targetAttrs" : "*", 7 | "rights" : "read, search", 8 | "actors" : [ 9 | "role=admin root" 10 | ] 11 | }, 12 | { 13 | "path" : "/", 14 | "name" : "Admins can update all resources", 15 | "targetAttrs" : "*", 16 | "rights" : "add, modify, delete", 17 | "actors" : [ 18 | "role=admin root" 19 | ] 20 | }, 21 | { 22 | "path" : "/Groups", 23 | "name" : "Allow Authenticated access to search groups", 24 | "targetAttrs" :"displayName,members", 25 | "rights" : "search", 26 | "actors" : ["role=user bearer root"] 27 | }, 28 | { 29 | "path" : "/Groups", 30 | "name" : "Allow Authenticated access read groups", 31 | "targetAttrs" :"displayName", 32 | "rights" : "read", 33 | "actors" : ["role=user bearer root"] 34 | }, 35 | { 36 | "path" : "/Users", 37 | "name" : "Allow Authenticated access to names and email addresses of Users", 38 | "targetAttrs" :"username,displayName,emails,name,phoneNumbers,ims,photos,nickName,profileUrl,title,preferredLanguage,locale,timezone", 39 | "rights" : "read, search", 40 | "actors" : ["role=user bearer root"] 41 | }, 42 | { 43 | "path" : "/Users", 44 | "name" : "Allow self read,search", 45 | "targetAttrs" :"*", 46 | "rights" : "read, search", 47 | "actors" : ["self"] 48 | }, 49 | { 50 | "path" : "/Users", 51 | "name" : "Allow self modification some personal attributes", 52 | "targetAttrs" :"username,displayName,emails,phoneNumbers,ims,photos,nickName,profileUrl,title,preferredLanguage,locale,timezone", 53 | "rights" : "modify", 54 | "actors" : ["self"] 55 | }, 56 | { 57 | "path" : "/ServiceProviderConfig", 58 | "name" : "Allow unauthenticated access to ServiceProviderConfig", 59 | "targetAttrs" :"*", 60 | "rights" : "read, search", 61 | "actors" : ["any"] 62 | }, 63 | { 64 | "path" : "/ResourceTypes", 65 | "name" : "Allow unauthenticated access to ResourceTypes", 66 | "targetAttrs" :"*", 67 | "rights" : "read, search", 68 | "actors" : ["any"] 69 | }, 70 | { 71 | "path" : "/Schemas", 72 | "name" : "Allow unauthenticated access to Schemas", 73 | "targetAttrs" :"*", 74 | "rights" : "read, search", 75 | "actors" : ["any"] 76 | } 77 | ] 78 | } -------------------------------------------------------------------------------- /opa/policy/i2scim-authz.rego: -------------------------------------------------------------------------------- 1 | package i2scim.authz 2 | 3 | import data.acis 4 | 5 | allow { 6 | count(rules) > 0 7 | } 8 | 9 | rules[rule] { 10 | some x 11 | startswith(input.path,acis[x].path) 12 | hasRight(acis[x],input.operation) 13 | isActorMatch(acis[x]) 14 | 15 | rule = acis[x] 16 | } 17 | 18 | hasRight(aci,right) { 19 | privs = split(aci.rights,", ") 20 | 21 | some i 22 | right == privs[i] 23 | } 24 | 25 | isActorMatch(aci) { 26 | some j 27 | actor = aci.actors[j] 28 | isTypeMatch(actor) 29 | } 30 | 31 | isTypeMatch(actor) { 32 | actor == "any" 33 | } 34 | 35 | isTypeMatch(actor) { 36 | actor == "self" 37 | input.path == "/Me" 38 | } 39 | 40 | isTypeMatch(actor) { 41 | # let scim evaluate 42 | startswith(actor,"ref") 43 | } 44 | 45 | isTypeMatch(actor) { 46 | # let scim evaluate 47 | startswith(actor,"filter") 48 | } 49 | 50 | isTypeMatch(actor) { 51 | startswith(actor,"role=") 52 | x := replace(actor,"role=","") 53 | vals = split(x," ") 54 | count(vals) > 0 55 | count(input.auth.roles) > 0 56 | some i,j 57 | input.auth.roles[i] == vals[j] 58 | } 59 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/1-i2scim-memory-configs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: scim-mem 5 | --- 6 | apiVersion: v1 7 | kind: Secret 8 | metadata: 9 | name: i2scim-root 10 | namespace: scim-mem 11 | type: Opaque 12 | data: 13 | #Base64 encoded values 14 | scim.security.root.username: YWRtaW4= 15 | scim.security.root.password: YWRtaW4= 16 | --- 17 | apiVersion: v1 18 | kind: ConfigMap 19 | metadata: 20 | namespace: scim-mem 21 | name: i2scim-mem-config 22 | data: 23 | scim.event.enable: "false" 24 | scim.prov.providerClass: com.independentid.scim.backend.memory.MemoryProvider 25 | scim.prov.memory.dir: "/scim/data" 26 | scim.prov.memory.file: "scimdb.json" 27 | scim.prov.memory.maxbackups: "10" 28 | scim.prov.memory.backup.mins: "60" 29 | # Indicates the attributes to be indexed 30 | scim.prov.memory.indexes: User:userName,User:emails.value,Group:displayName 31 | 32 | scim.resourcetype.path: "/config/resourceTypes.json" 33 | scim.schema.path: "/config/scimSchema.json" 34 | 35 | # Security Configuration 36 | scim.security.enable: "true" 37 | # Locations of the acis.json file to use 38 | scim.security.acis: "/config/acis.json" 39 | scim.security.root.enable: "true" 40 | # When basic is enabled, i2scim will attempt to process HTTP Basic Auth against User resources 41 | # located in the Memory provider database. 42 | scim.security.authen.basic: "true" 43 | 44 | # Configuration for JWT authentication 45 | scim.security.authen.jwt: "false" 46 | 47 | # The JWT claim used to match RBAC scopes used in acis processing 48 | scim.security.authen.jwt.claim.scope: "scope" 49 | 50 | # See: Quarkus Using JWT RBAC for configuration details 51 | # https://quarkus.io/guides/security-jwt 52 | quarkus.smallrye-jwt.enabled: "true" 53 | smallrye.jwt.always-check-authorization: "true" 54 | mp.jwt.verify.issuer: "test.i2scim.io" 55 | mp.jwt.verify.audiences: "aud.test.i2scim.io" 56 | #mp.jwt.verify.location: "https://example.com/jwkset.json" 57 | mp.jwt.verify.publickey: "eyJrZXlzIjpbeyJrdHkiOiJSU0EiLCJraWQiOiJpMnNjaW0iLCJ1c2UiOiJLZXkgdXNlZCBmb3Ig 58 | aTJzY2ltIHRlc3RpbmcgcHVycG9zZXMgT05MWSEiLCJuIjoidGFDUDM1bEZzODVZTm5qcEtxYkNB 59 | U2Fvc0Q3UWRaakduRHFXb1pzOTN3YllIYnFHUk1FVlE0WUluTmQ1TXNaS2NGM2dHdEhxbzBEVk1f 60 | Q0RpUklaeGNaWnV3WjNCQnRSbUJ1UWFmeXRPQ2tOWktqZm9PRTZwdG5ITzlvVGt5aEtpTkpJcy1s 61 | S1JsZFAtU0RVSFpfT3V4OGRBbkQta0poamlqSW5SSkprcXNhTy1nSDI2c3Y5NU83azVTMEptLUVS 62 | cjBUcWZvc3RmMGtfWU05ZWxZWFh6aDdDUWkzckdaOWgtY2Nja2tjczhpLUo0QlZWc0JEcnVPNVJ4 63 | dnR0NUtWRVVwMFB1Q3JMTHVxbUN1aGpMLUpkRTRFaXVvbWRKRGJBcW1tUVo2RWY2Z19uVUhfNFdj 64 | Q3REdE5fTGVyVGdFekl6OUQ3aThOVl8wSG8zMTFSOUx0NEdRIiwiZSI6IkFRQUIifV19" 65 | --- -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/2-i2scim-gke-memory-pvset.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Persistent Volume Claim for Google Cloud using GKE 3 | # 4 | apiVersion: v1 5 | kind: PersistentVolumeClaim 6 | metadata: 7 | namespace: scim-mem 8 | name: i2scim-pvc 9 | spec: 10 | storageClassName: premium-rwo 11 | accessModes: 12 | - ReadWriteOnce 13 | resources: 14 | requests: 15 | storage: 5Gi 16 | --- 17 | 18 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/2-i2scim-memory-pvset.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # PV and PVC set for running on NFS volume (e.g. on bare metal cluster) 3 | # 4 | apiVersion: v1 5 | kind: PersistentVolume 6 | metadata: 7 | name: i2scim-pv1 8 | namespace: scim-mem 9 | labels: 10 | app: i2scim 11 | spec: 12 | capacity: 13 | storage: 50Gi 14 | volumeMode: Filesystem 15 | accessModes: [ReadWriteOnce] 16 | persistentVolumeReclaimPolicy: Retain 17 | storageClassName: nfs 18 | mountOptions: 19 | - hard 20 | - nfsvers=4.1 21 | nfs: 22 | path: /nfs/data/i2scim-pv/rep1 23 | server: 10.1.10.110 24 | readOnly: false 25 | --- 26 | apiVersion: v1 27 | kind: PersistentVolume 28 | metadata: 29 | name: i2scim-pv2 30 | namespace: scim-mem 31 | labels: 32 | app: i2scim 33 | spec: 34 | capacity: 35 | storage: 50Gi 36 | volumeMode: Filesystem 37 | accessModes: [ReadWriteOnce] 38 | persistentVolumeReclaimPolicy: Retain 39 | storageClassName: nfs 40 | mountOptions: 41 | - hard 42 | - nfsvers=4.1 43 | nfs: 44 | path: /nfs/data/i2scim-pv/rep2 45 | server: 10.1.10.110 46 | readOnly: false 47 | --- 48 | apiVersion: v1 49 | kind: PersistentVolume 50 | metadata: 51 | name: i2scim-pv3 52 | namespace: scim-mem 53 | labels: 54 | app: i2scim 55 | spec: 56 | capacity: 57 | storage: 50Gi 58 | volumeMode: Filesystem 59 | accessModes: [ReadWriteOnce] 60 | persistentVolumeReclaimPolicy: Retain 61 | storageClassName: nfs 62 | mountOptions: 63 | - hard 64 | - nfsvers=4.1 65 | nfs: 66 | path: /nfs/data/i2scim-pv/rep3 67 | server: 10.1.10.110 68 | readOnly: false 69 | --- 70 | apiVersion: v1 71 | kind: PersistentVolumeClaim 72 | metadata: 73 | namespace: scim-mem 74 | name: i2scim-pvc 75 | spec: 76 | accessModes: 77 | - ReadWriteOnce 78 | storageClassName: nfs 79 | resources: 80 | requests: 81 | storage: 5Gi 82 | selector: 83 | matchLabels: 84 | app: i2scim 85 | --- 86 | 87 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/README.md: -------------------------------------------------------------------------------- 1 | # pkg-i2scim-prov-memory directory 2 | 3 | This directory is deprecated and has been replaced by the i2scim-universal directory. 4 | 5 | This directory provides docker build that bundles SCIM with Memory Provider only and provides example kubernetes 6 | configuration files. -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/deploy-instructions.md: -------------------------------------------------------------------------------- 1 | ## i2scim Using Memory Provider 2 | 3 | This packaging of i2scim deploys using the memory provider. Active information is stored in-memory for fast updates 4 | and queries. The memory provider persists data to disk on a scheduled cycle determined by configuration. 5 | 6 | Notice: This package is designed to be a demonstration for testing purposes of the implementation of SCIM protocol. 7 | This configuration does not include replication or multi-server support. A future enhancement will be made available 8 | separately to provide replication services based on Apache Kafka. For more information contact [info@independentid. 9 | com](mailto:info@independentid.com). 10 | 11 | ### Kubernetes Deployments 12 | 13 | To deploy i2scim in Kubernetes, 4 files are provided as templates as follows: 14 | 15 | * `1-i2scim-memory-configs.yaml` Defines the basic environment settings for the i2scim server. 16 | This includes defining secrets such as the root account for the server. 17 | 18 | * Persistent volume set definitions: 19 | - `2-i2scim-memory-pvset.yaml` defines the persistent volume sets and claims for the 20 | i2scim server using NFS (e.g. on bare metal cluster). 21 | - `2-i2scim-gke-memory-pvset.yaml` defines a persistent volume 22 | claim for Google Cloud. 23 | 24 | Modify these files as needed to create your kubernetes persistent volumes. These volumes will be used by i2sciim to 25 | persist SCIM data. Set the volume size to match the expected data set size. 26 | 27 | * `3-i2scim-config-schema.yaml` Defines the data model and access control the server will provide. i2scim works by 28 | automatically loading schema definitions and resource types at run time. Modify these configmaps to change the data 29 | model and access control for the server as follows: 30 | - `acis.json` The access control policy for the server. See [Access Control](../AccessControl.md) for information 31 | on the format of this file. 32 | - `resourceTypes.json` The ResourceTypes defined in this server. This file corresponds to 33 | [RFC7643 Section 6](https://datatracker.ietf.org/doc/html/rfc7643#section-6) and [RFC7644 Section 4](https://datatracker.ietf.org/doc/html/rfc7644#section-4) 34 | defining configuration discovery. 35 | - `scimCommonSchema.json` This file defines the common attributes used in all resource types in the server. **This 36 | file should not be changed as implementation is fixed.** 37 | - -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/scim/ReadMe.txt: -------------------------------------------------------------------------------- 1 | # This directory is used to become the root directory for the SCIM server on Docker. -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/src/main/docker/Dockerfile.native: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package -Pnative 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/i2scim-parent . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/i2scim-parent 15 | # 16 | ### 17 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.6 18 | WORKDIR /work/ 19 | RUN chown 1001 /work \ 20 | && chmod "g+rwX" /work \ 21 | && chown 1001:root /work 22 | COPY --chown=1001:root target/*-runner /work/application 23 | 24 | RUN mkdir /scim && chown 185 /scim 25 | 26 | EXPOSE 8080 27 | USER 1001 28 | 29 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] 30 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/src/main/docker/Dockerfile.native-micro: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # It uses a micro base image, tuned for Quarkus native executables. 4 | # It reduces the size of the resulting container image. 5 | # Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. 6 | # 7 | # Before building the container image run: 8 | # 9 | # ./mvnw package -Pnative 10 | # 11 | # Then, build the image with: 12 | # 13 | # docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/i2scim-parent . 14 | # 15 | # Then run the container using: 16 | # 17 | # docker run -i --rm -p 8080:8080 quarkus/i2scim-parent 18 | # 19 | ### 20 | FROM quay.io/quarkus/quarkus-micro-image:2.0 21 | WORKDIR /work/ 22 | RUN chown 1001 /work \ 23 | && chmod "g+rwX" /work \ 24 | && chown 1001:root /work 25 | COPY --chown=1001:root target/*-runner /work/application 26 | 27 | RUN mkdir /scim && chown 1001 /scim 28 | 29 | EXPOSE 8080 30 | USER 1001 31 | 32 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] 33 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 21 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021. Independent Identity Incorporated 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler 18 | 19 | ############################################################ 20 | # Handler specific properties. 21 | # Describes specific configuration info for Handlers. 22 | ############################################################ 23 | 24 | org.apache.juli.FileHandler.level = FINE 25 | org.apache.juli.FileHandler.directory = ${catalina.base}/logs 26 | org.apache.juli.FileHandler.prefix = ${classloader.webappName}. 27 | org.apache.juli.FileHandler.formatter = com.independentid.scim.log.JavaLogFormatter 28 | 29 | 30 | java.util.logging.ConsoleHandler.level = FINE 31 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/src/main/resources/resources-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources": [ 3 | { 4 | "pattern": ".*\\.json$" 5 | } 6 | ] 7 | } -------------------------------------------------------------------------------- /pkg-i2scim-prov-memory/src/main/resources/schema/acis.json: -------------------------------------------------------------------------------- 1 | { 2 | "acis": [ 3 | { 4 | "path" : "/", 5 | "name" : "Administrators can read, search, compare all records and operational attributes", 6 | "targetAttrs" : "*", 7 | "rights" : "read, search", 8 | "actors" : [ 9 | "role=admin root" 10 | ] 11 | }, 12 | { 13 | "path" : "/", 14 | "name" : "Admins can update all resources", 15 | "targetAttrs" : "*", 16 | "rights" : "add, modify, delete", 17 | "actors" : [ 18 | "role=admin root" 19 | ] 20 | }, 21 | { 22 | "path" : "/Groups", 23 | "name" : "Allow Authenticated access to search groups", 24 | "targetAttrs" :"displayName,members", 25 | "rights" : "search", 26 | "actors" : ["role=user bearer root"] 27 | }, 28 | { 29 | "path" : "/Groups", 30 | "name" : "Allow Authenticated access read groups", 31 | "targetAttrs" :"displayName", 32 | "rights" : "read", 33 | "actors" : ["role=user bearer root"] 34 | }, 35 | { 36 | "path" : "/Users", 37 | "name" : "Allow Authenticated access to names and email addresses of Users", 38 | "targetAttrs" :"username,displayName,emails,name,phoneNumbers,ims,photos,nickName,profileUrl,title,preferredLanguage,locale,timezone", 39 | "rights" : "read, search", 40 | "actors" : ["role=user bearer root"] 41 | }, 42 | { 43 | "path" : "/Users", 44 | "name" : "Allow self read,search", 45 | "targetAttrs" :"*", 46 | "rights" : "read, search", 47 | "actors" : ["self"] 48 | }, 49 | { 50 | "path" : "/Users", 51 | "name" : "Allow self modification some personal attributes", 52 | "targetAttrs" :"username,displayName,emails,phoneNumbers,ims,photos,nickName,profileUrl,title,preferredLanguage,locale,timezone", 53 | "rights" : "modify", 54 | "actors" : ["self"] 55 | }, 56 | { 57 | "path" : "/ServiceProviderConfig", 58 | "name" : "Allow unauthenticated access to ServiceProviderConfig", 59 | "targetAttrs" :"*", 60 | "rights" : "read, search", 61 | "actors" : ["any"] 62 | }, 63 | { 64 | "path" : "/ResourceTypes", 65 | "name" : "Allow unauthenticated access to ResourceTypes", 66 | "targetAttrs" :"*", 67 | "rights" : "read, search", 68 | "actors" : ["any"] 69 | }, 70 | { 71 | "path" : "/Schemas", 72 | "name" : "Allow unauthenticated access to Schemas", 73 | "targetAttrs" :"*", 74 | "rights" : "read, search", 75 | "actors" : ["any"] 76 | } 77 | ] 78 | } -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/2-i2scim-gke-mongo-pvset.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Persistent Volume Claim for Google Cloud using GKE. The pvc is only for system and access logs 3 | # and some server state, property files. 4 | # 5 | apiVersion: v1 6 | kind: PersistentVolumeClaim 7 | metadata: 8 | namespace: scim-mongo 9 | name: i2scim-pvc 10 | spec: 11 | storageClassName: standard 12 | accessModes: 13 | - ReadWriteOnce 14 | resources: 15 | requests: 16 | storage: 5Gi 17 | --- 18 | 19 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/2-i2scim-mongo-pvset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: i2scim-mongo-pv1 5 | namespace: scim-mongo 6 | labels: 7 | app: i2scim 8 | spec: 9 | capacity: 10 | storage: 50Gi 11 | volumeMode: Filesystem 12 | accessModes: [ReadWriteOnce] 13 | persistentVolumeReclaimPolicy: Retain 14 | storageClassName: i2scimlog 15 | mountOptions: 16 | - hard 17 | - nfsvers=4.1 18 | nfs: 19 | path: /nfs/data/i2scim-mongo-pv/rep1 20 | server: 10.1.10.110 21 | readOnly: false 22 | --- 23 | apiVersion: v1 24 | kind: PersistentVolume 25 | metadata: 26 | name: i2scim-mongo-pv2 27 | namespace: scim-mongo 28 | labels: 29 | app: i2scim 30 | spec: 31 | capacity: 32 | storage: 50Gi 33 | volumeMode: Filesystem 34 | accessModes: [ReadWriteOnce] 35 | persistentVolumeReclaimPolicy: Retain 36 | storageClassName: i2scimlog 37 | mountOptions: 38 | - hard 39 | - nfsvers=4.1 40 | nfs: 41 | path: /nfs/data/i2scim-mongo-pv/rep2 42 | server: 10.1.10.110 43 | readOnly: false 44 | --- 45 | apiVersion: v1 46 | kind: PersistentVolume 47 | metadata: 48 | name: i2scim-mongo-pv3 49 | namespace: scim-mongo 50 | labels: 51 | app: i2scim 52 | spec: 53 | capacity: 54 | storage: 50Gi 55 | volumeMode: Filesystem 56 | accessModes: [ReadWriteOnce] 57 | persistentVolumeReclaimPolicy: Retain 58 | storageClassName: i2scimlog 59 | mountOptions: 60 | - hard 61 | - nfsvers=4.1 62 | nfs: 63 | path: /nfs/data/i2scim-mongo-pv/rep3 64 | server: 10.1.10.110 65 | readOnly: false 66 | --- 67 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/README.md: -------------------------------------------------------------------------------- 1 | # pkg-i2scim-prov-mongodb directory 2 | 3 | This directory is deprecated and has been replaced by the i2scim-universal directory. 4 | 5 | This directory provides docker build that bundles SCIM with Mongo database Provider only and provides example kubernetes 6 | configuration files. -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/dbmongo-test-service.yaml: -------------------------------------------------------------------------------- 1 | # Source: mongodb/templates/svc-standalone.yaml 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: db-mongodb 6 | namespace: scim-mongo 7 | labels: 8 | app: mongodb 9 | release: "db" 10 | spec: 11 | type: ClusterIP 12 | ports: 13 | - name: mongodb 14 | port: 27017 15 | targetPort: mongodb 16 | selector: 17 | app: mongodb 18 | release: "db" 19 | --- 20 | # Source: mongodb/templates/deployment-standalone.yaml 21 | apiVersion: apps/v1 22 | kind: Deployment 23 | metadata: 24 | name: db-mongodb 25 | namespace: scim-mongo 26 | labels: 27 | app: mongodb 28 | release: "db" 29 | spec: 30 | strategy: 31 | type: RollingUpdate 32 | selector: 33 | matchLabels: 34 | app: mongodb 35 | release: "db" 36 | template: 37 | metadata: 38 | labels: 39 | app: mongodb 40 | release: "db" 41 | spec: 42 | containers: 43 | - name: db-mongodb 44 | image: docker.io/library/mongo:6.0.4 45 | imagePullPolicy: "IfNotPresent" 46 | env: 47 | - name: MONGO_INITDB_ROOT_USERNAME 48 | value: "admin" 49 | - name: MONGO_INITDB_ROOT_PASSWORD 50 | value: "t0p-Secret" 51 | - name: MONGODB_ENABLE_IPV6 52 | value: "no" 53 | - name: MONGODB_ENABLE_DIRECTORY_PER_DB 54 | value: "no" 55 | ports: 56 | - name: mongodb 57 | containerPort: 27017 58 | livenessProbe: 59 | exec: 60 | command: 61 | - mongo 62 | - --eval 63 | - "db.adminCommand('ping')" 64 | initialDelaySeconds: 30 65 | periodSeconds: 10 66 | timeoutSeconds: 5 67 | successThreshold: 1 68 | failureThreshold: 6 69 | readinessProbe: 70 | exec: 71 | command: 72 | - mongo 73 | - --eval 74 | - "db.adminCommand('ping')" 75 | initialDelaySeconds: 5 76 | periodSeconds: 10 77 | timeoutSeconds: 5 78 | successThreshold: 1 79 | failureThreshold: 6 80 | volumeMounts: 81 | - name: data 82 | mountPath: /data/db 83 | resources: 84 | {} 85 | volumes: 86 | - name: data 87 | emptyDir: {} -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/scim/ReadMe.txt: -------------------------------------------------------------------------------- 1 | # This directory is used to become the root directory for the SCIM server on Docker. -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/src/main/docker/Dockerfile.native: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package -Pnative 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/i2scim-parent . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/i2scim-parent 15 | # 16 | ### 17 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.6 18 | WORKDIR /work/ 19 | RUN chown 1001 /work \ 20 | && chmod "g+rwX" /work \ 21 | && chown 1001:root /work 22 | COPY --chown=1001:root target/*-runner /work/application 23 | 24 | RUN mkdir /scim && chown 185 /scim 25 | 26 | EXPOSE 8080 27 | USER 1001 28 | 29 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] 30 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/src/main/docker/Dockerfile.native-micro: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # It uses a micro base image, tuned for Quarkus native executables. 4 | # It reduces the size of the resulting container image. 5 | # Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. 6 | # 7 | # Before building the container image run: 8 | # 9 | # ./mvnw package -Pnative 10 | # 11 | # Then, build the image with: 12 | # 13 | # docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/i2scim-parent . 14 | # 15 | # Then run the container using: 16 | # 17 | # docker run -i --rm -p 8080:8080 quarkus/i2scim-parent 18 | # 19 | ### 20 | FROM quay.io/quarkus/quarkus-micro-image:2.0 21 | WORKDIR /work/ 22 | RUN chown 1001 /work \ 23 | && chmod "g+rwX" /work \ 24 | && chown 1001:root /work 25 | COPY --chown=1001:root target/*-runner /work/application 26 | 27 | RUN mkdir /scim && chown 1001 /scim 28 | 29 | EXPOSE 8080 30 | USER 1001 31 | 32 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] 33 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 21 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021. Independent Identity Incorporated 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler 18 | 19 | ############################################################ 20 | # Handler specific properties. 21 | # Describes specific configuration info for Handlers. 22 | ############################################################ 23 | 24 | org.apache.juli.FileHandler.level = FINE 25 | org.apache.juli.FileHandler.directory = ${catalina.base}/logs 26 | org.apache.juli.FileHandler.prefix = ${classloader.webappName}. 27 | org.apache.juli.FileHandler.formatter = com.independentid.scim.log.JavaLogFormatter 28 | 29 | 30 | java.util.logging.ConsoleHandler.level = FINE 31 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/src/main/resources/resources-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources": [ 3 | { 4 | "pattern": ".*\\.json$" 5 | } 6 | ] 7 | } -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/src/main/resources/schema/acis.json: -------------------------------------------------------------------------------- 1 | { 2 | "acis": [ 3 | { 4 | "path" : "/", 5 | "name" : "Administrators can read, search, compare all records and operational attributes", 6 | "targetAttrs" : "*", 7 | "rights" : "read, search", 8 | "actors" : [ 9 | "role=admin root" 10 | ] 11 | }, 12 | { 13 | "path" : "/", 14 | "name" : "Admins can update all resources", 15 | "targetAttrs" : "*", 16 | "rights" : "add, modify, delete", 17 | "actors" : [ 18 | "role=admin root" 19 | ] 20 | }, 21 | { 22 | "path" : "/Groups", 23 | "name" : "Allow Authenticated access to search groups", 24 | "targetAttrs" :"displayName,members", 25 | "rights" : "search", 26 | "actors" : ["role=user bearer root"] 27 | }, 28 | { 29 | "path" : "/Groups", 30 | "name" : "Allow Authenticated access read groups", 31 | "targetAttrs" :"displayName", 32 | "rights" : "read", 33 | "actors" : ["role=user bearer root"] 34 | }, 35 | { 36 | "path" : "/Users", 37 | "name" : "Allow Authenticated access to names and email addresses of Users", 38 | "targetAttrs" :"username,displayName,emails,name,phoneNumbers,ims,photos,nickName,profileUrl,title,preferredLanguage,locale,timezone", 39 | "rights" : "read, search", 40 | "actors" : ["role=user bearer root"] 41 | }, 42 | { 43 | "path" : "/Users", 44 | "name" : "Allow self read,search", 45 | "targetAttrs" :"*", 46 | "rights" : "read, search", 47 | "actors" : ["self"] 48 | }, 49 | { 50 | "path" : "/Users", 51 | "name" : "Allow self modification some personal attributes", 52 | "targetAttrs" :"username,displayName,emails,phoneNumbers,ims,photos,nickName,profileUrl,title,preferredLanguage,locale,timezone", 53 | "rights" : "modify", 54 | "actors" : ["self"] 55 | }, 56 | { 57 | "path" : "/ServiceProviderConfig", 58 | "name" : "Allow unauthenticated access to ServiceProviderConfig", 59 | "targetAttrs" :"*", 60 | "rights" : "read, search", 61 | "actors" : ["any"] 62 | }, 63 | { 64 | "path" : "/ResourceTypes", 65 | "name" : "Allow unauthenticated access to ResourceTypes", 66 | "targetAttrs" :"*", 67 | "rights" : "read, search", 68 | "actors" : ["any"] 69 | }, 70 | { 71 | "path" : "/Schemas", 72 | "name" : "Allow unauthenticated access to Schemas", 73 | "targetAttrs" :"*", 74 | "rights" : "read, search", 75 | "actors" : ["any"] 76 | } 77 | ] 78 | } -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/src/test/java/com/independentid/scim/test/http/ScimClientProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021. Independent Identity Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.independentid.scim.test.http; 18 | 19 | import com.independentid.scim.backend.mongo.MongoProvider; 20 | import io.quarkus.test.junit.QuarkusTestProfile; 21 | 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | public class ScimClientProfile implements QuarkusTestProfile { 26 | @Override 27 | public Map getConfigOverrides() { 28 | Map cmap = new HashMap<>(Map.of( 29 | "scim.schema.path","/schema/scimSchema.json", //this test schema changes some default returns for testing 30 | "scim.resourcetype.path","/schema/resourceTypes.json", 31 | 32 | "scim.prov.providerClass", MongoProvider.class.getName(), 33 | 34 | //"scim.prov.mongo.dbname", "testHttpSCIM", 35 | //"scim.prov.mongo.uri","mongodb://localhost:27017", 36 | //"scim.prov.providerClass","com.independentid.scim.backend.mongo.MongoProvider", 37 | 38 | "quarkus.http.test-port","0", 39 | "quarkus.log.min-level","DEBUG", 40 | "logging.level.com.independentid.scim","INFO", 41 | "quarkus.log.category.\"com.independentid.scim.test\".level","INFO" 42 | )); 43 | cmap.putAll(Map.of( 44 | "scim.json.pretty","true", 45 | "scim.security.enable", "false", 46 | "scim.event.enable","false", 47 | "scim.root.dir","." //enables local debug testing 48 | )); 49 | return cmap; 50 | } 51 | 52 | @Override 53 | public String getConfigProfile() { 54 | return "ScimHttpTestProfile"; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /pkg-i2scim-prov-mongodb/src/test/resources/data/cluster-config.prop: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021. Independent Identity Incorporated 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # Properties file containing run configuration for tests. 18 | 19 | # Address of the K8S cluster running scim 20 | cluster_url=http://10.1.10.10:8080/ 21 | # Number of client requester threads 22 | threads=10 23 | # Data set to load 24 | # user-10pretty.json, user-1000.json, user-5000.json 25 | # data generated by RandomUser.me 26 | dataset=/data/user-5000.json -------------------------------------------------------------------------------- /spec/schema/scim-bulkRequest.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "https://raw.githubusercontent.com/i2-open/i2scim/master/spec/schema/scim-bulkRequest.schema.json", 4 | "title": "SCIM Bulk Operations Request", 5 | "description": "JSON Schema for a SCIM Bulk Operations Request per Sec 3.7 RFC7644", 6 | "type": "object", 7 | "required": ["schemas","Operations"], 8 | "properties": { 9 | "schemas": { 10 | "type": "array", 11 | "items": { 12 | "enum": [ 13 | "urn:ietf:params:scim:api:messages:2.0:BulkRequest" 14 | ] 15 | } 16 | }, 17 | "failOnErrors": { 18 | "type": "integer" 19 | }, 20 | "Operations": { 21 | "type": "array", 22 | "items": { 23 | "type": "object", 24 | "required": ["method","path"], 25 | "properties": { 26 | "method": { 27 | "description": "The type of SCIM operation to perform", 28 | "enum": ["POST", "PUT", "PATCH", "DELETE"] 29 | }, 30 | "bulkId": { 31 | "description": "The transient identifier of a newly created resource, unique within a bulk request and created by the client. ", 32 | "type": "string" 33 | }, 34 | "version": { 35 | "description": "The current ETag resource version to apply an ETag pre-condition", 36 | "type": "string" 37 | }, 38 | "path": { 39 | "description": "The resources relative path to the SCIM service provider root. e.g. `/Users/`", 40 | "type": "string" 41 | }, 42 | "data": { 43 | "description": "The resource data as it would appear in the payload of a SCIM POST, PUT, or PATCH operation", 44 | "type": "object", 45 | "oneOf": [ 46 | {"$ref": "https://raw.githubusercontent.com/i2-open/i2scim/master/spec/schema/scim-createResourceRequest.schema.json"}, 47 | {"$ref": "https://raw.githubusercontent.com/i2-open/i2scim/master/spec/schema/scim-resource.schema.json"}, 48 | {"$ref": "https://raw.githubusercontent.com/i2-open/i2scim/master/spec/schema/scim-patchRequest.schema.json"} 49 | ] 50 | } 51 | } 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /spec/schema/scim-createResourceRequest.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "https://raw.githubusercontent.com/i2-open/i2scim/master/spec/schema/scim-createResourceRequest.schema.json", 4 | "title": "SCIM Create Resource Request Schema", 5 | "description": "JSON-Schema for creating a SCIM Resource per RFC7644. Note this base schema only validates required attributes.", 6 | "type": "object", 7 | "required": ["schemas"], 8 | "properties": { 9 | "schemas" : { 10 | "type": "array", 11 | "description": "One SCIM SCIM Schema URI (describing the object) plus optional schema extension URIs", 12 | "items": { 13 | "type": "string" 14 | } 15 | }, 16 | "id": { 17 | "type": "string", 18 | "description": "An unique identifier for the object (ignored on SCIM create)." 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /spec/schema/scim-errorResponse.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "https://raw.githubusercontent.com/i2-open/i2scim/master/spec/schema/scim-errorResponse.schema.json", 4 | "title": "SCIM Error Response Schema", 5 | "description": "JSON-Schema for a SCIM Error Response per RFC7644", 6 | "type": "object", 7 | "required": ["schemas","status"], 8 | "properties": { 9 | "schemas" : { 10 | "type": "array", 11 | "description": "This SCIM JSON Schema describes a SCIMv2 Protocol error response", 12 | "items": { 13 | "enum": ["urn:ietf:params:scim:api:messages:2.0:Error"] 14 | } 15 | }, 16 | "detail": { 17 | "type": "string", 18 | "description": "Human readable description of the error." 19 | }, 20 | "status": { 21 | "type": "string", 22 | "description": "The HTTP status code (See Section 6 of RFC7231) expressed as a JSON String." 23 | }, 24 | "scimType": { 25 | "enum": ["invalidFilter","tooMany","uniqueness","mutability","invalidSyntax","invalidPath","noTarget","invalidValue","invalidVers","sensitive"], 26 | "description": "Indicates the SCIM protocol error type when HTTP Status 400 (Bad Request) is returned." 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /spec/schema/scim-listResponse.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "https://raw.githubusercontent.com/i2-open/i2scim/master/spec/schema/scim-listResponse.schema.json", 4 | "title": "SCIM List Response", 5 | "description": "JSON-Schema for a SCIM ListResponse (in response to a search) per RFC7644", 6 | "type": "object", 7 | "required": ["schemas","totalResults","Resources"], 8 | "properties": { 9 | "schemas" : { 10 | "type": "array", 11 | "description": "This SCIM Schema describes a SCIM Protocol ListResponse for returning query results", 12 | "items": { 13 | "type": "string", 14 | "enum": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"] 15 | } 16 | }, 17 | "totalResults": { 18 | "type": "integer", 19 | "description": "The total number of results available in the query" 20 | }, 21 | "startIndex": { 22 | "type": "integer", 23 | "description": "The 1-based index of the first result in the current set\nof list results. REQUIRED when partial results are returned due\nto pagination.", 24 | "minimum": 0 25 | }, 26 | "itemsPerPage": { 27 | "type": "integer", 28 | "minimum": 1, 29 | "description": "The number of resources returned in a list response\npage. REQUIRED when partial results are returned due to\npagination." 30 | }, 31 | "Resources": { 32 | "type": "array", 33 | "description": "Resources consists of a set of SCIM Resource JSON objects returned.", 34 | "items": { 35 | "type": "object" 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /spec/schema/scim-patchRequest.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "https://raw.githubusercontent.com/i2-open/i2scim/master/spec/schema/scim-patchRequest.schema.json", 4 | "title": "SCIM Patch Request", 5 | "description": "Json-Schema for a SCIM Patch Request per RFC7644 Sec 3.5.2", 6 | "type": "object", 7 | "required": ["schemas","Operations"], 8 | "properties": { 9 | "schemas": { 10 | "type": "array", 11 | "items": { 12 | "enum": [ 13 | "urn:ietf:params:scim:api:messages:2.0:PatchOp" 14 | ] 15 | } 16 | }, 17 | "Operations": { 18 | "type": "array", 19 | "minItems": 1, 20 | "items": { 21 | "required": ["op"], 22 | "properties": { 23 | "op": { 24 | "description": "The type of operation to be performed", 25 | "enum": [ 26 | "add", "remove", "replace" 27 | ] 28 | }, 29 | "path" : { 30 | "description": "A SCIM path describing the attribute and/or value instance to be modified (See Fig 7 RFC7644)", 31 | "type": "string" 32 | }, 33 | "value": { 34 | "description": "A SCIM Patch value which MAY be any JSON value, object, or array", 35 | "anyOf": [ 36 | {"type": "array"}, 37 | {"type": "string"}, 38 | {"type": "object"}, 39 | {"type": "integer"}, 40 | {"type": "boolean"} 41 | ] 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /spec/schema/scim-resource.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": " $ref: https://raw.githubusercontent.com/i2-open/i2scim/master/spec/schema/scim-resource.schema.json\n", 4 | "title": "SCIM Resource Schema", 5 | "description": "Json-Schema for a basic SCIM Resource per RFC7644. Note this base schema only validates required attributes (id and schema).", 6 | "type": "object", 7 | "required": ["schemas","id"], 8 | "properties": { 9 | "schemas" : { 10 | "type": "array", 11 | "description": "One SCIM SCIM Schema URI (describing the object) plus optional schema extension URIs", 12 | "items": { 13 | "type": "string" 14 | } 15 | }, 16 | "id": { 17 | "type": "string", 18 | "description": "An unique identifier for the object" 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /spec/schema/scim-searchRequest.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "https://raw.githubusercontent.com/i2-open/i2scim/master/spec/schema/scim-searchRequest.schema.json", 4 | "title": "SCIM Search Request", 5 | "description": "JSON Schema for a SCIM Search Request per Sec 3.4.3 RFC7644", 6 | "type": "object", 7 | "required": ["schemas"], 8 | "properties": { 9 | "schemas": { 10 | "type": "array", 11 | "items": { 12 | "enum": [ 13 | "urn:ietf:params:scim:api:messages:2.0:SearchRequest" 14 | ] 15 | } 16 | }, 17 | "attributes": { 18 | "type": "array", 19 | "items": { 20 | "type": "string" 21 | } 22 | }, 23 | "excludedAttributes": { 24 | "type": "array", 25 | "items": { 26 | "type": "string" 27 | } 28 | }, 29 | "filter": { 30 | "type": "string" 31 | }, 32 | "sortBy": { 33 | "type": "string" 34 | }, 35 | "sortOrder": { 36 | "type": "string", 37 | "enum": ["ascending","descending"] 38 | }, 39 | "startIndex": { 40 | "type": "integer", 41 | "minimum": 0 42 | }, 43 | "count": { 44 | "type": "integer", 45 | "minimum": 1 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /spec/schema/scim-serviceProviderConfigResponse.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "https://raw.githubusercontent.com/i2-open/i2scim/master/spec/schema/scim-serviceProviderConfigResponse.schema.json", 4 | 5 | "title": "ServiceProviderConfig Response Schema", 6 | "description": "JSON-Schema for Service Provider Config discovery repsonse per Sec 4 RFC7644", 7 | "type": "object", 8 | "required": [ 9 | "schemas", 10 | "id", 11 | "patch", 12 | "bulk", 13 | "filter", 14 | "changePassword", 15 | "sort", 16 | "etag" 17 | ], 18 | "properties": { 19 | "schemas": { 20 | "type": "array", 21 | "description": "SCIM Schemas attribute which indicates ServiceProviderConfig", 22 | "items": { 23 | "enum": [ 24 | "urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig" 25 | ] 26 | } 27 | }, 28 | "documentationUri": { 29 | "type": "string", 30 | "description": "An HTTP-addressable URL pointing to the service provider's human-consumable help documentation." 31 | }, 32 | "patch": { 33 | "type": "object", 34 | "description": "A Boolean value specifying whether or not the operation is supported.", 35 | "properties": { 36 | "supported": { 37 | "type": "boolean" 38 | } 39 | } 40 | }, 41 | "bulk": { 42 | "type": "object", 43 | "description": "A Boolean value specifying whether or not the bulk operation is supported.", 44 | "properties": { 45 | "supported": { 46 | "type": "boolean" 47 | } 48 | } 49 | }, 50 | "filter": { 51 | "type": "object", 52 | "description": "A Boolean value specifying whether or not filter searches are supported.", 53 | "properties": { 54 | "supported": { 55 | "type": "boolean" 56 | } 57 | } 58 | }, 59 | "changePassword": { 60 | "type": "object", 61 | "description": "A Boolean value specifying whether or not change password is supported.", 62 | "properties": { 63 | "supported": { 64 | "type": "boolean" 65 | } 66 | } 67 | }, 68 | "sort": { 69 | "type": "object", 70 | "description": "A Boolean value specifying whether or not sort is supported.", 71 | "properties": { 72 | "supported": { 73 | "type": "boolean" 74 | } 75 | } 76 | }, 77 | "etag": { 78 | "type": "object", 79 | "description": "A Boolean value specifying whether or not etag and pre-conditions are supported.", 80 | "properties": { 81 | "supported": { 82 | "type": "boolean" 83 | } 84 | } 85 | } 86 | } 87 | } --------------------------------------------------------------------------------