/project/core/Security/SecurityManagerBase.cs

https://github.com/bertvan/CruiseControl.NET · C# · 382 lines · 213 code · 30 blank · 139 comment · 20 complexity · 5451151d6482d1a12d4002b5c5148221 MD5 · raw file

  1. using Exortech.NetReflector;
  2. using System;
  3. using System.Collections.Generic;
  4. using ThoughtWorks.CruiseControl.Core.Util;
  5. using ThoughtWorks.CruiseControl.Remote;
  6. using ThoughtWorks.CruiseControl.Remote.Security;
  7. using ThoughtWorks.CruiseControl.Core.Security.Auditing;
  8. using ThoughtWorks.CruiseControl.Remote.Messages;
  9. namespace ThoughtWorks.CruiseControl.Core.Security
  10. {
  11. /// <summary>
  12. /// Provides some base security manager functionality.
  13. /// </summary>
  14. public abstract class SecurityManagerBase
  15. : ISecurityManager
  16. {
  17. #region Private constants
  18. private const string displayNameKey = "DisplayName";
  19. #endregion
  20. #region Private fields
  21. private ISessionCache sessionCache = new InMemorySessionCache();
  22. private IAuditLogger[] loggers = new IAuditLogger[0];
  23. private IAuditReader reader;
  24. private Permissions permissions = new Permissions();
  25. #endregion
  26. #region Public properties
  27. #region SessionCache
  28. /// <summary>
  29. /// The associated session cache.
  30. /// </summary>
  31. /// <version>1.5</version>
  32. /// <default><link>In Memory Security Cache</link></default>
  33. [ReflectorProperty("cache", InstanceTypeKey = "type", Required = false)]
  34. public ISessionCache SessionCache
  35. {
  36. get { return sessionCache; }
  37. set { sessionCache = value; }
  38. }
  39. #endregion
  40. #region AuditLoggers
  41. /// <summary>
  42. /// The audit loggers.
  43. /// </summary>
  44. /// <version>1.5</version>
  45. /// <default>None</default>
  46. [ReflectorProperty("audit", Required=false)]
  47. public IAuditLogger[] AuditLoggers
  48. {
  49. get { return loggers; }
  50. set { loggers = value; }
  51. }
  52. #endregion
  53. #region AuditReader
  54. /// <summary>
  55. /// The audit reader.
  56. /// </summary>
  57. /// <version>1.5</version>
  58. /// <default>None</default>
  59. [ReflectorProperty("auditReader", InstanceTypeKey = "type", Required = false)]
  60. public IAuditReader AuditReader
  61. {
  62. get { return reader; }
  63. set { reader = value; }
  64. }
  65. #endregion
  66. #region Permissions
  67. /// <summary>
  68. /// The default permissions.
  69. /// </summary>
  70. /// <version>1.5</version>
  71. /// <default>None</default>
  72. [ReflectorProperty("defaults", Required=false, InstanceType=typeof(Permissions))]
  73. public Permissions DefaultPermissions
  74. {
  75. get { return permissions; }
  76. set { permissions = value; }
  77. }
  78. #endregion
  79. #region RequiresSession
  80. /// <summary>
  81. /// Does this manager require a session?
  82. /// </summary>
  83. public bool RequiresSession
  84. {
  85. get { return permissions.DefaultRight == SecurityRight.Deny; }
  86. }
  87. #endregion
  88. #region Channel
  89. /// <summary>
  90. /// The channel security requirements.
  91. /// </summary>
  92. /// <version>1.5</version>
  93. /// <default>None</default>
  94. [ReflectorProperty("channel", InstanceTypeKey = "type", Required = false)]
  95. public virtual IChannelSecurity Channel { get; set; }
  96. #endregion
  97. #region Hash
  98. /// <summary>
  99. /// Gets or sets the hash.
  100. /// </summary>
  101. /// <value>
  102. /// The hash.
  103. /// </value>
  104. public byte[] Hash { get; set; }
  105. #endregion
  106. #endregion
  107. #region Public methods
  108. #region Initialise()
  109. /// <summary>
  110. /// Initialise the security manager.
  111. /// </summary>
  112. public abstract void Initialise();
  113. #endregion
  114. #region RetrieveUser()
  115. /// <summary>
  116. /// Retrieves a user from the store.
  117. /// </summary>
  118. /// <param name="identifier"></param>
  119. /// <returns></returns>
  120. public abstract IAuthentication RetrieveUser(string identifier);
  121. #endregion
  122. #region RetrievePermission()
  123. /// <summary>
  124. /// Retrieves a permission from the store.
  125. /// </summary>
  126. /// <param name="identifier"></param>
  127. /// <returns></returns>
  128. public abstract IPermission RetrievePermission(string identifier);
  129. #endregion
  130. #region Login()
  131. /// <summary>
  132. /// Starts a new session for a user.
  133. /// </summary>
  134. /// <param name="credentials">The credentials to use.</param>
  135. /// <returns>The session token if the credentials are valid, null otherwise.</returns>
  136. public virtual string Login(LoginRequest credentials)
  137. {
  138. string sessionToken = null;
  139. // Find the authentication
  140. string identifier = NameValuePair.FindNamedValue(credentials.Credentials,
  141. LoginRequest.UserNameCredential);
  142. IAuthentication authentication = RetrieveUser(identifier);
  143. string userName = credentials.Identifier;
  144. string displayName = null;
  145. if (authentication != null)
  146. {
  147. userName = authentication.GetUserName(credentials);
  148. // Attempt to authenticate
  149. if (authentication.Authenticate(credentials))
  150. {
  151. // Start a new session
  152. sessionToken = sessionCache.AddToCache(userName);
  153. displayName = authentication.GetDisplayName(credentials);
  154. sessionCache.StoreSessionValue(sessionToken, displayNameKey, displayName);
  155. }
  156. }
  157. if (sessionToken != null)
  158. {
  159. Log.Debug(string.Format(System.Globalization.CultureInfo.CurrentCulture,"{0} [{1}] has logged in", displayName, userName));
  160. LogEvent(null, userName, SecurityEvent.Login, SecurityRight.Allow, null);
  161. }
  162. else
  163. {
  164. Log.Warning(string.Format(System.Globalization.CultureInfo.CurrentCulture,"Login failure: {0} has failed to login", userName));
  165. LogEvent(null, userName, SecurityEvent.Login, SecurityRight.Deny, null);
  166. }
  167. return sessionToken;
  168. }
  169. #endregion
  170. #region Logout()
  171. /// <summary>
  172. /// Terminates a user session.
  173. /// </summary>
  174. /// <param name="sessionToken">The token of the user session.</param>
  175. public virtual void Logout(string sessionToken)
  176. {
  177. string userName = sessionCache.RetrieveFromCache(sessionToken);
  178. if (!string.IsNullOrEmpty(userName))
  179. {
  180. sessionCache.RemoveFromCache(sessionToken);
  181. Log.Debug(string.Format(System.Globalization.CultureInfo.CurrentCulture,"{0} has logged out", userName));
  182. LogEvent(null, userName, SecurityEvent.Logout, SecurityRight.Allow, null);
  183. }
  184. else
  185. {
  186. LogEvent(null, null, SecurityEvent.Logout, SecurityRight.Deny, "Session has already been logged out");
  187. }
  188. }
  189. #endregion
  190. #region ValidateSession()
  191. /// <summary>
  192. /// Checks that a session is still validate (e.g. hasn't timed out or been terminated.)
  193. /// </summary>
  194. /// <param name="sessionToken">The session token.</param>
  195. /// <returns>True if the session is valid, false otherwise.</returns>
  196. public virtual bool ValidateSession(string sessionToken)
  197. {
  198. if (sessionToken == null) return false;
  199. string userName = sessionCache.RetrieveFromCache(sessionToken);
  200. return (userName != null);
  201. }
  202. #endregion
  203. #region GetUserName()
  204. /// <summary>
  205. /// Retrieves the user name from a session token.
  206. /// </summary>
  207. /// <param name="sessionToken">The session token.</param>
  208. /// <returns>The name of the user if the session is valid, null otherwise.</returns>
  209. /// <remarks>
  210. /// The session token must be the user name.
  211. /// </remarks>
  212. public virtual string GetUserName(string sessionToken)
  213. {
  214. if (sessionToken == null) return null;
  215. string userName = sessionCache.RetrieveFromCache(sessionToken);
  216. return userName;
  217. }
  218. #endregion
  219. #region GetDisplayName()
  220. /// <summary>
  221. /// Retrieves the display name from a session token.
  222. /// </summary>
  223. /// <param name="sessionToken">The session token.</param>
  224. /// <param name="displayName">The display name that was sent from the client.</param>
  225. /// <returns>
  226. /// The name of the user if the session is valid, null otherwise.
  227. /// </returns>
  228. public virtual string GetDisplayName(string sessionToken, string displayName)
  229. {
  230. if (sessionToken == null) return null;
  231. var actualDisplayName = sessionCache.RetrieveSessionValue(sessionToken, displayNameKey) as string;
  232. return actualDisplayName;
  233. }
  234. #endregion
  235. #region LogEvent()
  236. /// <summary>
  237. /// Sends a security event to the audit loggers.
  238. /// </summary>
  239. /// <param name="projectName">The name of the project.</param>
  240. /// <param name="userName">The name of the user.</param>
  241. /// <param name="eventType">The type of event.</param>
  242. /// <param name="eventRight">The right of the event.</param>
  243. /// <param name="message">Any security message.</param>
  244. public virtual void LogEvent(string projectName, string userName, SecurityEvent eventType, SecurityRight eventRight, string message)
  245. {
  246. if (loggers != null)
  247. {
  248. foreach (IAuditLogger logger in loggers)
  249. {
  250. logger.LogEvent(projectName, userName, eventType, eventRight, message);
  251. }
  252. }
  253. }
  254. #endregion
  255. #region ListAllUsers()
  256. /// <summary>
  257. /// Lists all the users who have been defined in the system.
  258. /// </summary>
  259. /// <returns>
  260. /// A list of <see cref="UserDetails"/> containing the details on all the users
  261. /// who have been defined.
  262. /// </returns>
  263. public abstract List<UserDetails> ListAllUsers();
  264. #endregion
  265. #region CheckServerPermission()
  266. /// <summary>
  267. /// Checks whether the user can perform the specified action at the server level.
  268. /// </summary>
  269. /// <param name="userName">The name of the user that is being checked.</param>
  270. /// <param name="permission">The permission to check.</param>
  271. /// <returns>True if the permission is valid, false otherwise.</returns>
  272. public abstract bool CheckServerPermission(string userName, SecurityPermission permission);
  273. #endregion
  274. #region ReadAuditRecords()
  275. /// <summary>
  276. /// Reads all the specified number of audit events.
  277. /// </summary>
  278. /// <param name="startPosition">The starting position.</param>
  279. /// <param name="numberOfRecords">The number of records to read.</param>
  280. /// <returns>A list of <see cref="AuditRecord"/>s containing the audit details.</returns>
  281. public virtual List<AuditRecord> ReadAuditRecords(int startPosition, int numberOfRecords)
  282. {
  283. List<AuditRecord> records = new List<AuditRecord>();
  284. if (reader != null) records = reader.Read(startPosition, numberOfRecords);
  285. return records;
  286. }
  287. #endregion
  288. #region ReadAuditRecords()
  289. /// <summary>
  290. /// Reads all the specified number of filtered audit events.
  291. /// </summary>
  292. /// <param name="startPosition">The starting position.</param>
  293. /// <param name="numberOfRecords">The number of records to read.</param>
  294. /// <param name="filter">The filter to use.</param>
  295. /// <returns>A list of <see cref="AuditRecord"/>s containing the audit details that match the filter.</returns>
  296. public virtual List<AuditRecord> ReadAuditRecords(int startPosition, int numberOfRecords, AuditFilterBase filter)
  297. {
  298. List<AuditRecord> records = new List<AuditRecord>();
  299. if (reader != null) records = reader.Read(startPosition, numberOfRecords, filter);
  300. return records;
  301. }
  302. #endregion
  303. #region ChangePassword()
  304. /// <summary>
  305. /// Changes the password of the user.
  306. /// </summary>
  307. /// <param name="sessionToken">The session token for the current user.</param>
  308. /// <param name="oldPassword">The person's old password.</param>
  309. /// <param name="newPassword">The person's new password.</param>
  310. public virtual void ChangePassword(string sessionToken, string oldPassword, string newPassword)
  311. {
  312. throw new NotImplementedException("Password management is not allowed for this security manager");
  313. }
  314. #endregion
  315. #region ResetPassword()
  316. /// <summary>
  317. /// Resets the password for a user.
  318. /// </summary>
  319. /// <param name="sessionToken">The session token for the current user.</param>
  320. /// <param name="userName">The user name to reset the password for.</param>
  321. /// <param name="newPassword">The person's new password.</param>
  322. public virtual void ResetPassword(string sessionToken, string userName, string newPassword)
  323. {
  324. throw new NotImplementedException("Password management is not allowed for this security manager");
  325. }
  326. #endregion
  327. #region RetrieveComponent()
  328. /// <summary>
  329. /// Retrieves a component from the security manager.
  330. /// </summary>
  331. /// <typeparam name="TComponent">The type of component to retrieve.</typeparam>
  332. /// <returns>The component of the specified type, if available, null otherwise.</returns>
  333. public TComponent RetrieveComponent<TComponent>()
  334. where TComponent : class
  335. {
  336. return null;
  337. }
  338. #endregion
  339. #region GetDefaultRight()
  340. /// <summary>
  341. /// Gets the default right for a permission.
  342. /// </summary>
  343. /// <param name="permission">The permission to retrieve the default for.</param>
  344. /// <returns>The default right.</returns>
  345. public virtual SecurityRight GetDefaultRight(SecurityPermission permission)
  346. {
  347. return permissions.GetPermission(permission);
  348. }
  349. #endregion
  350. #endregion
  351. }
  352. }