Implement Create/Delete/List person users functionality in ssoAdminClient
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace VMware.vSphere.SsoAdminClient
|
||||
{
|
||||
public class Class1
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// **************************************************************************
|
||||
// Copyright (c) VMware, Inc. All rights reserved. -- VMware Confidential.
|
||||
// **************************************************************************
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VMware.vSphere.SsoAdminClient.DataTypes
|
||||
{
|
||||
public class Principal
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Domain { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string FirstName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public string EmailAddress { get; set; }
|
||||
|
||||
public override string ToString() {
|
||||
return $"{Name}@{Domain}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
// **************************************************************************
|
||||
// Copyright (c) VMware, Inc. All rights reserved. -- VMware Confidential.
|
||||
// **************************************************************************
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Selectors;
|
||||
using System.Security;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Security;
|
||||
using System.Text;
|
||||
using VMware.Binding.WsTrust;
|
||||
using VMware.Binding.WsTrust.SecurityContext;
|
||||
using VMware.vSphere.LsClient;
|
||||
using VMware.vSphere.SsoAdminClient.DataTypes;
|
||||
using VMware.vSphere.SsoAdminClient.SsoAdminServiceReferencer;
|
||||
|
||||
namespace VMware.vSphere.SsoAdminClient
|
||||
{
|
||||
public class SsoAdminClient
|
||||
{
|
||||
private const int WEB_OPERATION_TIMEOUT_SECONDS = 30;
|
||||
|
||||
private string _server;
|
||||
private SsoPortTypeClient _ssoAdminBindingClient;
|
||||
private UserPassSecurityContext _securityContext;
|
||||
|
||||
public SsoAdminClient(string hostname, string user, SecureString password, X509CertificateValidator serverCertificateValidator) {
|
||||
if (hostname == null) throw new ArgumentNullException(nameof(hostname));
|
||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||
if (password == null) throw new ArgumentNullException(nameof(password));
|
||||
|
||||
_server = hostname;
|
||||
var lsClient = new LookupServiceClient(hostname, serverCertificateValidator);
|
||||
|
||||
// Create STS Client
|
||||
var stsUri = lsClient.GetStsEndpointUri();
|
||||
_securityContext = new UserPassSecurityContext(user, password, stsUri, serverCertificateValidator);
|
||||
|
||||
// Create SSO Admin Binding Client
|
||||
var ssoAdminUri = lsClient.GetSsoAdminEndpointUri();
|
||||
_ssoAdminBindingClient = new SsoPortTypeClient(GetBinding(), new EndpointAddress(ssoAdminUri));
|
||||
_ssoAdminBindingClient.ChannelFactory.Endpoint.EndpointBehaviors.Add(new WsTrustBehavior());
|
||||
|
||||
var serverAuthentication = GetServerAuthentication(serverCertificateValidator);
|
||||
|
||||
if (serverAuthentication != null) {
|
||||
_ssoAdminBindingClient
|
||||
.ChannelFactory
|
||||
.Credentials
|
||||
.ServiceCertificate
|
||||
.SslCertificateAuthentication = serverAuthentication;
|
||||
}
|
||||
}
|
||||
|
||||
#region Private Helpers
|
||||
private X509ServiceCertificateAuthentication GetServerAuthentication(X509CertificateValidator serverCertificateValidator) {
|
||||
if (serverCertificateValidator != null) {
|
||||
return new X509ServiceCertificateAuthentication {
|
||||
CertificateValidationMode = X509CertificateValidationMode.Custom,
|
||||
CustomCertificateValidator = serverCertificateValidator
|
||||
};
|
||||
}
|
||||
|
||||
// Default .NET behavior for TLS certificate validation
|
||||
return null;
|
||||
}
|
||||
|
||||
private static MessageEncodingBindingElement GetWcfEncoding() {
|
||||
// VMware STS requires SOAP version 1.1
|
||||
return new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
|
||||
}
|
||||
|
||||
private static HttpsTransportBindingElement GetWcfTransport(bool useSystemProxy) {
|
||||
// Communication with the STS is over https
|
||||
HttpsTransportBindingElement transport = new HttpsTransportBindingElement {
|
||||
RequireClientCertificate = false
|
||||
};
|
||||
|
||||
transport.UseDefaultWebProxy = useSystemProxy;
|
||||
transport.MaxBufferSize = 2147483647;
|
||||
transport.MaxReceivedMessageSize = 2147483647;
|
||||
|
||||
return transport;
|
||||
}
|
||||
|
||||
private static CustomBinding GetBinding() {
|
||||
|
||||
// There is no build-in WCF binding capable of communicating
|
||||
// with VMware STS, so we create a plain custom one.
|
||||
// This binding does not provide support for WS-Trust,
|
||||
// that support is currently implemented as a WCF endpoint behaviour.
|
||||
var binding = new CustomBinding(GetWcfEncoding(), GetWcfTransport(true));
|
||||
|
||||
var timeout = TimeSpan.FromSeconds(WEB_OPERATION_TIMEOUT_SECONDS);
|
||||
binding.CloseTimeout = timeout;
|
||||
binding.OpenTimeout = timeout;
|
||||
binding.ReceiveTimeout = timeout;
|
||||
binding.SendTimeout = timeout;
|
||||
|
||||
return binding;
|
||||
}
|
||||
|
||||
private WsSecurityContext CreateAuthorizedInvocationContext() {
|
||||
// Issue Bearer token to authorize create solution user to SSO Admin service
|
||||
var bearerToken = _securityContext.GetToken();
|
||||
|
||||
// Set WS Trust Header Serialization with issued bearer SAML token
|
||||
var securityContext = new WsSecurityContext {
|
||||
ClientChannel = _ssoAdminBindingClient.InnerChannel,
|
||||
Properties = {
|
||||
Credentials = {
|
||||
BearerToken = bearerToken
|
||||
}
|
||||
}
|
||||
};
|
||||
return securityContext;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public interface
|
||||
|
||||
public Principal CreateLocalUser(
|
||||
string userName,
|
||||
string password,
|
||||
string description = null,
|
||||
string emailAddress = null,
|
||||
string firstName = null,
|
||||
string lastName = null) {
|
||||
|
||||
// Create Authorization Invocation Context
|
||||
var authorizedInvocationContext =
|
||||
CreateAuthorizedInvocationContext();
|
||||
|
||||
// Invoke SSO Admin CreateLocalSolutionUser operation
|
||||
var ssoPrincipalId = authorizedInvocationContext.
|
||||
InvokeOperation(() =>
|
||||
_ssoAdminBindingClient.CreateLocalPersonUserAsync(
|
||||
new ManagedObjectReference {
|
||||
type = "SsoAdminPrincipalManagementService",
|
||||
Value = "principalManagementService"
|
||||
},
|
||||
userName,
|
||||
new SsoAdminPersonDetails {
|
||||
description = description,
|
||||
emailAddress = emailAddress,
|
||||
firstName = firstName,
|
||||
lastName = lastName
|
||||
},
|
||||
password)).Result;
|
||||
|
||||
return GetLocalUsers(ssoPrincipalId.name, ssoPrincipalId.domain, authorizedInvocationContext);
|
||||
}
|
||||
|
||||
private Principal GetLocalUsers(string userName, string domain, WsSecurityContext wsSecurityContext) {
|
||||
// Invoke SSO Admin FindPersonUserAsync operation
|
||||
var personUser = wsSecurityContext.
|
||||
InvokeOperation(() =>
|
||||
_ssoAdminBindingClient.FindPersonUserAsync(
|
||||
new ManagedObjectReference {
|
||||
type = "SsoAdminPrincipalDiscoveryService",
|
||||
Value = "principalDiscoveryService"
|
||||
},
|
||||
new SsoPrincipalId {
|
||||
name = userName,
|
||||
domain = domain
|
||||
})).Result;
|
||||
return new Principal {
|
||||
Name = personUser.id.name,
|
||||
Domain = personUser.id.domain,
|
||||
Description = personUser.details.description,
|
||||
FirstName = personUser.details.firstName,
|
||||
LastName = personUser.details.lastName,
|
||||
EmailAddress = personUser.details.emailAddress
|
||||
};
|
||||
}
|
||||
|
||||
public IEnumerable<Principal> GetAllLocalUsers() {
|
||||
// Create Authorization Invocation Context
|
||||
var authorizedInvocationContext =
|
||||
CreateAuthorizedInvocationContext();
|
||||
|
||||
// Invoke SSO Admin FindPersonUsersAsync operation
|
||||
var personUsers = authorizedInvocationContext.
|
||||
InvokeOperation(() =>
|
||||
_ssoAdminBindingClient.FindPersonUsersAsync(
|
||||
new ManagedObjectReference {
|
||||
type = "SsoAdminPrincipalDiscoveryService",
|
||||
Value = "principalDiscoveryService"
|
||||
},
|
||||
new SsoAdminPrincipalDiscoveryServiceSearchCriteria (),
|
||||
int.MaxValue)).Result.returnval;
|
||||
|
||||
foreach (var personUser in personUsers) {
|
||||
yield return new Principal {
|
||||
Name = personUser.id.name,
|
||||
Domain = personUser.id.domain,
|
||||
Description = personUser.details.description,
|
||||
FirstName = personUser.details.firstName,
|
||||
LastName = personUser.details.lastName,
|
||||
EmailAddress = personUser.details.emailAddress
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteLocalUser(
|
||||
Principal principal) {
|
||||
|
||||
// Create Authorization Invocation Context
|
||||
var authorizedInvocationContext =
|
||||
CreateAuthorizedInvocationContext();
|
||||
|
||||
// Invoke SSO Admin DeleteLocalPrincipal operation
|
||||
authorizedInvocationContext.
|
||||
InvokeOperation(() =>
|
||||
_ssoAdminBindingClient.DeleteLocalPrincipalAsync(
|
||||
new ManagedObjectReference {
|
||||
type = "SsoAdminPrincipalManagementService",
|
||||
Value = "principalManagementService"
|
||||
},
|
||||
principal.Name));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
// **************************************************************************
|
||||
// Copyright (c) VMware, Inc. All rights reserved. -- VMware Confidential.
|
||||
// **************************************************************************
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Selectors;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using VMware.Binding.Sts;
|
||||
|
||||
namespace VMware.vSphere.SsoAdminClient
|
||||
{
|
||||
public class UserPassSecurityContext
|
||||
{
|
||||
private string _user;
|
||||
private SecureString _password;
|
||||
private VmwareSecruityTokenService _stsClient;
|
||||
public UserPassSecurityContext(
|
||||
string user,
|
||||
SecureString password,
|
||||
Uri stsUri,
|
||||
X509CertificateValidator serverCertificateValidator) {
|
||||
|
||||
if (user == null) throw new ArgumentNullException(nameof(user));
|
||||
if (password == null) throw new ArgumentNullException(nameof(password));
|
||||
if (stsUri == null) throw new ArgumentNullException(nameof(stsUri));
|
||||
|
||||
_user = user;
|
||||
_password = password;
|
||||
|
||||
Action<X509Certificate2> certHandler = null;
|
||||
if (serverCertificateValidator != null) {
|
||||
certHandler = serverCertificateValidator.Validate;
|
||||
}
|
||||
_stsClient = new VmwareSecruityTokenService(stsUri, false, certHandler);
|
||||
}
|
||||
|
||||
public XmlElement GetToken() {
|
||||
return _stsClient.IssueBearerTokenByUserCredential(
|
||||
_user,
|
||||
_password).RawToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,5 +6,35 @@
|
||||
<Description>SSO Admin API client.</Description>
|
||||
<TargetFrameworks>net45;netcoreapp2.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net45' ">
|
||||
<DefineConstants>$(DefineConstants);NET45</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">
|
||||
<DefineConstants>$(DefineConstants);NETCORE20</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
|
||||
<Reference Include="System.IdentityModel" />
|
||||
<PackageReference Include="System.ServiceModel.Primitives" Version="4.4.0" />
|
||||
<PackageReference Include="System.ServiceModel.Duplex" Version="4.4.0" />
|
||||
<PackageReference Include="System.ServiceModel.Http" Version="4.4.0" />
|
||||
<PackageReference Include="System.ServiceModel.NetTcp" Version="4.4.0" />
|
||||
<PackageReference Include="System.ServiceModel.Security" Version="4.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
|
||||
<PackageReference Include="VMware.System.Private.ServiceModel" Version="4.4.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="VMware.Binding.Sts" Version="12.0.0.15939652" />
|
||||
<PackageReference Include="VMware.Binding.WsTrust" Version="12.0.0.15939652" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VMware.vSphere.LsClient\VMware.vSphere.LsClient.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user