Example: Update the security store
The following examples use the SecurityControl feature in the Diffusion™ API to update the security store.
JavaScript
// Session security allows you to change the principal that a session is authenticated as. // It also allows users to query and update server-side security and authentication stores, // which control users, roles and permissions. This enables you to manage the capabilities // that any logged in user will have access to. // Connect to Diffusion with control client credentials const session = await diffusion.connect({ host : 'diffusion.example.com', port : 443, secure : true, principal : 'control', credentials : 'password' }); // 1. A session change their principal by re-authenticating await session.security.changePrincipal('admin', 'password'); console.log('Authenticated as admin'); // 2. The security configuration provides details about roles and their assigned permissions try { const config = await session.security.getSecurityConfiguration(); console.log('Roles for anonymous sessions: ', config.anonymous); console.log('Roles for named sessions: ', config.named); console.log('Available roles: ', config.roles); } catch(error) { console.log('Unable to fetch security configuration', error); } // 3. Changes to the security configuration are done with a SecurityScriptBuilder const securityScriptBuilder = session.security.securityScriptBuilder(); // Set the permissions for a particular role - global and topic-scoped // Each method on a script builder returns a new builder const setPermissionScript = securityScriptBuilder .setGlobalPermissions('SUPERUSER', ['REGISTER_HANDLER']) .setPathPermissions('SUPERUSER', '/foo', ['UPDATE_TOPIC']) .build(); // Update the server-side store with the generated script try { await session.security.updateSecurityStore(setPermissionScript); console.log('Security configuration updated successfully'); } catch(error) { console.log('Failed to update security configuration: ', error); } // 4. The system authentication configuration lists all users & roles try { const config = await session.security.getSystemAuthenticationConfiguration(); console.log('System principals: ', config.principals); console.log('Anonymous sessions: ', config.anonymous); } catch(error) { console.log('Unable to fetch system authentication configuration', error); } // 5. Changes to the system authentication config are done with a SystemAuthenticationScriptBuilder const authenticationScriptBuilder = session.security.authenticationScriptBuilder(); // Add a new user and set password & roles. const addUserScript = authenticationScriptBuilder .addPrincipal('Superman', 'correcthorsebatterystapler') .assignRoles('Superman', ['SUPERUSER']) .build(); // Update the system authentication store try { await session.security.updateAuthenticationStore(addUserScript); console.log('Updated system authentication config'); } catch(error) { console.log('Failed to update system authentication: ', error); }
.NET
/** * Copyright © 2021 - 2023 DiffusionData Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using PushTechnology.ClientInterface.Client.Factories; using PushTechnology.ClientInterface.Client.Features.Control.Clients.SecurityControl; using PushTechnology.ClientInterface.Client.Session; using PushTechnology.ClientInterface.Client.Types; using static System.Console; namespace PushTechnology.ClientInterface.Example { /// <summary> /// Client implementation that demonstrates how to update the security store. /// </summary> public sealed class SecurityControl { public async Task SecurityControlExample(string serverUrl) { // Connect as an admin session var session = Diffusion.Sessions.Principal("admin").Password("password") .CertificateValidation((cert, chain, errors) => CertificateValidationResult.ACCEPT) .Open(serverUrl); string role = "ADMINISTRATOR"; IReadOnlyCollection<GlobalPermission> defaultPermissions = null; ISecurityConfiguration securityConfig = null; try { //Get the default global permissions for the Admin role. securityConfig = await session.SecurityControl.GetSecurityAsync(); var adminRole = securityConfig.Roles.Where(x => x.Name == role).FirstOrDefault(); defaultPermissions = adminRole.GlobalPermissions; WriteLine($"The Administrator role has the following global permissions by default:"); foreach (var permission in defaultPermissions) { WriteLine($"'{permission}'"); } } catch (Exception ex) { WriteLine($"Failed to get global permissions : {ex}."); } try { //Add the following global permissions for the Admin role. var permissions = new List<GlobalPermission>(defaultPermissions); permissions.AddRange(new[] { GlobalPermission.REGISTER_HANDLER, GlobalPermission.VIEW_SESSION }); WriteLine($"Adding further permissions..."); string script = session.SecurityControl.Script.SetGlobalPermissions(role, permissions).ToScript(); await session.SecurityControl.UpdateStoreAsync(script); } catch (Exception ex) { WriteLine($"Failed to set global permissions : {ex}."); } finally { session.Close(); } } } }
Java and Android
/******************************************************************************* * Copyright (C) 2023 DiffusionData Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.pushtechnology.client.sdk.manual; import com.pushtechnology.diffusion.client.Diffusion; import com.pushtechnology.diffusion.client.features.control.clients.SecurityControl; import com.pushtechnology.diffusion.client.features.control.clients.SecurityControl.ScriptBuilder; import com.pushtechnology.diffusion.client.features.control.clients.SecurityControl.SecurityConfiguration; import com.pushtechnology.diffusion.client.session.Session; import com.pushtechnology.diffusion.client.types.GlobalPermission; import com.pushtechnology.diffusion.client.types.PathPermission; import java.util.HashSet; import java.util.Set; /** * An example of using a control client to alter the security configuration. * * This uses the 'SecurityControl' feature * * @author DiffusionData Limited */ public final class SecurityControlExample { public static void main(String[] args) { final Session session = Diffusion.sessions() .principal("admin") .password("password") .open("ws://localhost:8080"); final SecurityControl securityControl = session.feature(SecurityControl.class); final ScriptBuilder scriptBuilder = securityControl.scriptBuilder(); final Set<GlobalPermission> globalPermissions = new HashSet<GlobalPermission>() {{ add(GlobalPermission.VIEW_SERVER); add(GlobalPermission.VIEW_SESSION); }}; // add the given global permissions to the 'CLIENT' role scriptBuilder.setGlobalPermissions("CLIENT", globalPermissions); final Set<PathPermission> pathPermissions = new HashSet<PathPermission>() {{ add(PathPermission.UPDATE_TOPIC); add(PathPermission.MODIFY_TOPIC); }}; // set the given default path permissions for the 'CLIENT' role scriptBuilder.setDefaultPathPermissions("CLIENT", pathPermissions); final Set<String> roles = new HashSet<String>() {{ add("TOPIC_CONTROL"); add("CLIENT_CONTROL"); }}; // include the given roles within the 'OPERATOR' role scriptBuilder.setRoleIncludes("OPERATOR", roles); // update the security store securityControl.updateStore(scriptBuilder.script()).join(); // get the security configuration and print out all roles final SecurityConfiguration configuration = securityControl.getSecurity().join(); configuration.getRoles().forEach(System.out::println); session.close(); } }
C
/** * Copyright © 2021 - 2023 DiffusionData Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdio.h> #include <stdlib.h> #ifndef WIN32 #include <unistd.h> #else #define sleep(x) Sleep(1000 * x) #endif #include "diffusion.h" static int on_get_security_store( SESSION_T *session, const SECURITY_STORE_T store, void *context) { char **anonymous_roles = get_security_default_anonymous_roles(store); printf("Default anonymous roles: "); while (*anonymous_roles != NULL) { printf("%s ", *anonymous_roles); anonymous_roles++; } printf("\n"); char **named_roles = get_security_default_named_roles(store); printf("Default named roles: "); while (*named_roles != NULL) { printf("%s ", *named_roles); named_roles++; } printf("\n"); char **isolated_paths = get_security_isolated_paths(store); printf("Isolated paths: "); while (*isolated_paths != NULL) { printf("%s ", *isolated_paths); isolated_paths++; } printf("\n"); return HANDLER_SUCCESS; } static int on_update_security_store( SESSION_T *session, const LIST_T *error_reports, void *context) { // security store has been updated return HANDLER_SUCCESS; } int main(int argc, char **argv) { const char *url = "ws://localhost:8080"; const char *principal = "admin"; const char *password = "password"; CREDENTIALS_T *credentials = credentials_create_password(password); SESSION_T *session; DIFFUSION_ERROR_T error = { 0 }; // Create a session, synchronously session = session_create(url, principal, credentials, NULL, NULL, &error); if(session == NULL) { printf("Failed to create session: %s\n", error.message); free(error.message); credentials_free(credentials); return EXIT_FAILURE; } // Retrieve security store from Diffusion server const GET_SECURITY_STORE_PARAMS_T get_params = { .on_get = on_get_security_store, }; get_security_store(session, get_params); // Sleep for a while sleep(5); // update the security store with new path permissions SET_T *new_perms = set_new_int(5); set_add(new_perms, &SECURITY_PATH_PERMISSIONS_TABLE[PATH_PERMISSION_READ_TOPIC]); set_add(new_perms, &SECURITY_PATH_PERMISSIONS_TABLE[PATH_PERMISSION_UPDATE_TOPIC]); SCRIPT_T *script = script_create(); script = update_security_store_default_path_permissions(script, "foo", new_perms); set_free(new_perms); const UPDATE_SECURITY_STORE_PARAMS_T update_params = { .on_update = on_update_security_store, .update_script = script }; update_security_store(session, update_params); script_free(script); // Sleep for a while sleep(5); // Close the session, and release resources and memory session_close(session, NULL); session_free(session); credentials_free(credentials); return EXIT_SUCCESS; }
Change the URL from that provided in the example to the URL of the Diffusion server .