Skip to content

Commit

Permalink
Merge branch 'ust_18972/api_to_use_secret_databse' of github.com:Elaa…
Browse files Browse the repository at this point in the history
…dF/rudder into ust_19023/add_ui_to_manage_secrets
  • Loading branch information
ElaadF committed Apr 9, 2021
2 parents c27696c + 01d227f commit 19cda1a
Show file tree
Hide file tree
Showing 14 changed files with 190 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,12 @@ package com.normation.rudder.domain.secrets
import net.liftweb.json.JsonAST.JValue
import net.liftweb.json.JsonDSL._

final case class Secret(name: String, value: String)
final case class Secret(name: String, value: String, description: String)

object Secret {

def serializeSecret(secret : Secret): JValue = {
( ("name" -> secret.name)
~ ("value" -> secret.value)
)
def serializeSecretInfo(secret : Secret): JValue = {
( ("name" -> secret.name)
~ ("description" -> secret.description)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ final case class AddSecretDiff(secret: Secret) extends SecretDiff
final case class DeleteSecretDiff(secret: Secret) extends SecretDiff

final case class ModifySecretDiff(
name : String
, value : String
, modValue : Option[SimpleDiff[String]] = None
name : String
, description : String
, modValue : Boolean
, modDescription : Option[SimpleDiff[String]] = None
) extends SecretDiff

Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ class EventLogJdbcRepository(
) match {
case Right(log) => log
case Left(error) =>
println(error)
logEffect.warn(s"Error when trying to get the event type, recorded type was: '${eventType}'")
UnspecializedEventLog(eventLogDetails)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -855,15 +855,17 @@ class EventLogDetailsServiceImpl(
(s"Entry type is not a Secret: ${entry}")
name <- (secret \ "name").headOption.map( _.text ) ?~!
(s"Missing attribute 'name' in entry type Secret: ${entry}")
value <- (secret \ "value").headOption.map( _.text ) ?~!
(s"Missing attribute 'value' in entry type Secret: ${entry}")
modValue <- getFromToString((secret \ "diffValue").headOption)
description <- (secret \ "description").headOption.map( _.text ) ?~!
(s"Missing attribute 'description' in entry type Secret: ${entry}")
modValue <- tryo{(secret \ "valueHasChanged").text.toBoolean}
modDescription <- getFromToString((secret \ "diffDescription").headOption)
fileFormatOk <- TestFileFormat(secret)
} yield {
ModifySecretDiff(
name = name
, value = value
, description = description
, modValue = (modValue)
, modDescription = (modDescription)
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ class EventLogFactoryImpl(
) : AddSecret = {
val details = EventLog.withContent(secretXmlSerializer.serialise(secret) % ("changeType" -> "add"))
AddSecret(EventLogDetails(
id = id
id = id
, modificationId = modificationId
, principal = principal
, details = details
Expand All @@ -789,7 +789,7 @@ class EventLogFactoryImpl(

val details = EventLog.withContent(secretXmlSerializer.serialise(secret) % ("changeType" -> "delete"))
DeleteSecret(EventLogDetails(
id = id
id = id
, modificationId = modificationId
, principal = principal
, details = details
Expand All @@ -809,13 +809,25 @@ class EventLogFactoryImpl(
, reason : Option[String]
) : ModifySecret = {

val diffValue = SimpleDiff.stringToXml(<diffValue/>, SimpleDiff(oldSecret.value, newSecret.value) )
val diffValue = {
if(oldSecret.value != newSecret.value)
<valueHasChanged> True </valueHasChanged>
else
<valueHasChanged> False </valueHasChanged>
}

val diffDescription = {
if(oldSecret.description != newSecret.description)
Some(SimpleDiff.stringToXml(<diffDescription/>, SimpleDiff(oldSecret.description, newSecret.description) ))
else
None
}

val details = EventLog.withContent{
scala.xml.Utility.trim(<secret changeType="modify" fileFormat={Constants.XML_CURRENT_FILE_FORMAT.toString}>
<name>{oldSecret.name}</name>
<value>{oldSecret.value}</value>
{diffValue}
<description>{oldSecret.description}</description>
{diffValue ++ diffDescription}
</secret>)
}
ModifySecret(EventLogDetails(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ class SecretSerialisationImpl(xmlVersion:String) extends SecretSerialisation {
def serialise(secret:Secret): Elem = {
createTrimedElem(XML_TAG_SECRET, xmlVersion) (
<name>{secret.name}</name>
<value>{secret.value}</value>
<description>{secret.description}</description>
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -663,10 +663,11 @@ class SecretUnserialisationImpl extends SecretUnserialisation {
}
fileFormatOk <- TestFileFormat(secret)

name <- (secret \ "name").headOption.map( _.text ) ?~! ("Missing attribute 'name' in entry type globalParameter : " + entry)
value <- (secret \ "value").headOption.map( _.text ) ?~! ("Missing attribute 'value' in entry type globalParameter : " + entry)
name <- (secret \ "name").headOption.map( _.text ) ?~! ("Missing attribute 'name' in entry type secret : " + entry)
// value <- (secret \ "value").headOption.map( _.text ) ?~! ("Missing attribute 'value' in entry type secret : " + entry)
description <- (secret \ "description").headOption.map( _.text ) ?~! ("Missing attribute 'description' in entry type secret : " + entry)
} yield {
Secret(name, value)
Secret(name, "", description)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -754,29 +754,34 @@ object UserApi extends ApiModuleProvider[UserApi] {
}


sealed trait SecretVaultApi extends EndpointSchema with GeneralApi with SortIndex
object SecretVaultApi extends ApiModuleProvider[SecretVaultApi] {
final case object GetSecrets extends SecretVaultApi with ZeroParam with StartsAtVersion13 with SortIndex { val z = implicitly[Line].value
val description = "Get the list of key-value pair secret"
sealed trait SecretApi extends EndpointSchema with GeneralApi with SortIndex
object SecretApi extends ApiModuleProvider[SecretApi] {
final case object GetAllSecret extends SecretApi with ZeroParam with StartsAtVersion13 with SortIndex { val z = implicitly[Line].value
val description = "Get the list of key-value pair secret"
val (action, path) = GET / "secret"
}

final case object AddSecret extends SecretVaultApi with ZeroParam with StartsAtVersion13 with SortIndex { val z = implicitly[Line].value
val description = "Add a key-value pair secret"
final case object GetSecret extends SecretApi with OneParam with StartsAtVersion13 with SortIndex { val z = implicitly[Line].value
val description = "Get one key-value pair secret"
val (action, path) = GET / "secret" / "{id}"
}

final case object AddSecret extends SecretApi with ZeroParam with StartsAtVersion13 with SortIndex { val z = implicitly[Line].value
val description = "Add a key-value pair secret"
val (action, path) = PUT / "secret"
}

final case object UpdateSecret extends SecretVaultApi with ZeroParam with StartsAtVersion13 with SortIndex { val z = implicitly[Line].value
val description = "Update an existing key-value pair secret"
final case object UpdateSecret extends SecretApi with ZeroParam with StartsAtVersion13 with SortIndex { val z = implicitly[Line].value
val description = "Update an existing key-value pair secret"
val (action, path) = POST / "secret"
}

final case object DeleteSecret extends SecretVaultApi with OneParam with StartsAtVersion13 with SortIndex { val z = implicitly[Line].value
val description = "Delete a secret"
final case object DeleteSecret extends SecretApi with OneParam with StartsAtVersion13 with SortIndex { val z = implicitly[Line].value
val description = "Delete a secret"
val (action, path) = DELETE / "secret" / "{id}"
}

def endpoints = ca.mrvisser.sealerate.values[SecretVaultApi].toList.sortBy( _.z )
def endpoints = ca.mrvisser.sealerate.values[SecretApi].toList.sortBy( _.z )

}

Expand All @@ -797,7 +802,7 @@ object AllApi {
RuleApi.endpoints :::
InventoryApi.endpoints :::
InfoApi.endpoints :::
SecretVaultApi.endpoints :::
SecretApi.endpoints :::
// UserApi is not declared here, it will be contributed by plugin
Nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -1315,10 +1315,12 @@ final case class RestExtractorService (
for {
name <- extractJsonString(json,"name")
value <- extractJsonString(json, "value")
s <- (name, value) match {
case (None, v) => Failure(s"Missing name parameter for secret entry when parsing request")
case (n, None) => Failure(s"Missing value parameter for secret entry when parsing request")
case (Some(n), Some(v)) => Full(Secret(n,v))
description <- extractJsonString(json, "description")
s <- (name, value, description) match {
case (None, v, d) => Failure(s"Missing `name` parameter for secret entry when parsing request")
case (n, None, d) => Failure(s"Missing `value` parameter for secret entry when parsing request")
case (n, v, None) => Failure(s"Missing `description` parameter for secret entry when parsing request")
case (Some(n), Some(v), Some(d)) => Full(Secret(n,v,d))
}
} yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ final case object OnlyAdmin extends AuthorizationApiMapping {
SystemApi.ArchivesFullList.x :: SystemApi.ArchivesGroupsList.x :: SystemApi.ArchivesRulesList.x ::
SystemApi.GetAllZipArchive.x :: SystemApi.GetDirectivesZipArchive.x :: SystemApi.GetGroupsZipArchive.x ::
SystemApi.GetRulesZipArchive.x :: SystemApi.Info.x :: SystemApi.Status.x :: SystemApi.ArchivesParametersList.x ::
SystemApi.GetParametersZipArchive.x :: SystemApi.GetHealthcheckResult.x :: SecretVaultApi.GetSecrets.x ::
SecretVaultApi.AddSecret.x :: SecretVaultApi.DeleteSecret.x :: SecretVaultApi.UpdateSecret.x :: Nil
SystemApi.GetParametersZipArchive.x :: SystemApi.GetHealthcheckResult.x :: SecretApi.GetAllSecret.x ::
SecretApi.GetSecret.x :: SecretApi.AddSecret.x :: SecretApi.DeleteSecret.x :: SecretApi.UpdateSecret.x :: Nil
case Administration.Write => SettingsApi.ModifySettings.x :: SettingsApi.ModifySetting.x :: SystemApi.endpoints.map(_.x)
case Administration.Edit => SettingsApi.ModifySettings.x :: SettingsApi.ModifySetting.x :: SystemApi.endpoints.map(_.x)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,19 @@
package com.normation.rudder.rest.lift

import com.normation.box._
import com.normation.errors.IOResult
import com.normation.rudder.domain.secrets.Secret
import com.normation.rudder.rest.ApiPath
import com.normation.rudder.rest.ApiVersion
import com.normation.rudder.rest.AuthzToken
import com.normation.rudder.rest.RestExtractorService
import com.normation.rudder.rest.RestUtils
import com.normation.rudder.rest.{SecretVaultApi => API}
import com.normation.rudder.rest.{SecretApi => API}
import com.normation.rudder.web.services.SecretService
import net.liftweb.common._
import net.liftweb.http.LiftResponse
import net.liftweb.http.Req
import net.liftweb.json.JArray
import net.liftweb.json.JsonDSL._
import net.liftweb.json.JString


class SecretApi(
Expand All @@ -62,35 +62,48 @@ class SecretApi(
def getLiftEndpoints(): List[LiftApiModule] = {
API.endpoints.map(
e => e match {
case API.GetSecrets => GetSecrets
case API.GetAllSecret => GetAllSecret
case API.GetSecret => GetSecret
case API.AddSecret => AddSecret
case API.UpdateSecret => UpdateSecret
case API.DeleteSecret => DeleteSecret
}
)
}

object GetSecrets extends LiftApiModule0 {
val schema = API.GetSecrets
object GetAllSecret extends LiftApiModule0 {
val schema = API.GetAllSecret
val restExtractor = restExtractorService

def process0(version: ApiVersion, path: ApiPath, req: Req, params: DefaultParams, authzToken: AuthzToken): LiftResponse = {
implicit val prettify = params.prettify
implicit val action = schema.name
implicit val action = schema.name

val res = for {
secrets <- secretService.getSecrets
secrets <- secretService.getAllSecret.toBox
} yield {
secrets.map(Secret.serializeSecret)
JArray(secrets.map(Secret.serializeSecretInfo))
}

res.toBox match {
case Full(json) =>
RestUtils.toJsonResponse(None, JArray(json))
case eb: EmptyBox =>
val message = (eb ?~ s"Error when trying get secret from file").messageChain
RestUtils.toJsonError(None, message)(action, true)
RestUtils.response(restExtractor, "secrets", None)(res, req, "Error when trying to get all secrets")
}
}

object GetSecret extends LiftApiModule {
val schema = API.GetSecret
val restExtractor = restExtractorService

def process(version: ApiVersion, path: ApiPath, id: String, req: Req, params: DefaultParams, authzToken: AuthzToken): LiftResponse = {
implicit val prettify = params.prettify
implicit val action = schema.name

val res = for {
secret <- secretService.getSecretById(id).notOptional(s"Could not find secret with `${id}` name").toBox
} yield {
JArray(List(Secret.serializeSecretInfo(secret)))
}

RestUtils.response(restExtractor, "secrets", None)(res, req, s"Error when trying to get secret `${id}` value")
}
}

Expand All @@ -104,18 +117,12 @@ class SecretApi(

val res = for {
secret <- restExtractorService.extractSecret(req)
_ <- secretService.addSecret(secret).toBox
_ <- secretService.addSecret(secret, "Add a secret").toBox
} yield {
Secret.serializeSecret(secret)
JArray(List(Secret.serializeSecretInfo(secret)))
}

res match {
case Full(json) =>
RestUtils.toJsonResponse(None, json)
case eb: EmptyBox =>
val message = (eb ?~ s"Error when trying add a secret entry").messageChain
RestUtils.toJsonError(None, message)(action, true)
}
RestUtils.response(restExtractor, "secrets", None)(res, req, "Error when trying to add a secret")
}
}

Expand All @@ -128,18 +135,16 @@ class SecretApi(
implicit val action = schema.name

val res = for {
_ <- secretService.deleteSecret(id).toBox
toDelete <- secretService.getSecretById(id).toBox
_ <- secretService.deleteSecret(id, "Delete a secret").toBox
} yield {
id
toDelete match {
case Some(s) => JArray(List(Secret.serializeSecretInfo(s)))
case None => JArray(List(Secret.serializeSecretInfo(Secret(id, "", "")))) // don't know what to do here
}
}

res match {
case Full(secretId) =>
RestUtils.toJsonResponse(None, secretId)
case eb: EmptyBox =>
val message = (eb ?~ s"Error when trying delete a secret entry").messageChain
RestUtils.toJsonError(None, message)(action, true)
}
RestUtils.response(restExtractor, "secrets", None)(res, req, "Error when trying to delete a secret")
}
}

Expand All @@ -153,17 +158,12 @@ class SecretApi(

val res = for {
secret <- restExtractorService.extractSecret(req)
_ <- secretService.updateSecret(secret).toBox
_ <- secretService.updateSecret(secret, "Update a secret").toBox
} yield {
Secret.serializeSecret(secret)
}
res match {
case Full(json) =>
RestUtils.toJsonResponse(None, json)
case eb: EmptyBox =>
val message = (eb ?~ s"Error when trying update a secret entry").messageChain
RestUtils.toJsonError(None, message)(action, true)
JArray(List(Secret.serializeSecretInfo(secret)))
}

RestUtils.response(restExtractor, "secrets", None)(res, req, s"Error when trying to update a secret")
}
}

Expand Down
Loading

0 comments on commit 19cda1a

Please sign in to comment.