Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
ElaadF committed Mar 9, 2021
1 parent f143c60 commit 4443cf0
Show file tree
Hide file tree
Showing 7 changed files with 367 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,33 @@ object UserApi extends ApiModuleProvider[UserApi] {
def endpoints = ca.mrvisser.sealerate.values[UserApi].toList.sortBy( _.z )
}


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"
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"
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"
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"
val (action, path) = DELETE / "secret" / "{id}"
}

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

}

/*
* All API.
*/
Expand All @@ -770,6 +797,7 @@ object AllApi {
RuleApi.endpoints :::
InventoryApi.endpoints :::
InfoApi.endpoints :::
SecretVaultApi.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 @@ -38,7 +38,6 @@
package com.normation.rudder.rest

import java.io.StringReader

import com.normation.cfclerk.services.TechniqueRepository
import com.normation.inventory.domain.NodeId
import com.normation.rudder.api.{AclPath, ApiAccountId, ApiAccountName, ApiAclElement, HttpAction, ApiAuthorization => ApiAuthz}
Expand Down Expand Up @@ -103,6 +102,7 @@ import com.normation.rudder.domain.nodes.GroupProperty
import com.normation.rudder.domain.nodes.InheritMode
import com.normation.rudder.ncf.ParameterType.ParameterTypeService
import com.normation.rudder.services.policies.PropertyParser
import com.normation.rudder.web.services.Secret
import com.normation.utils.DateFormaterService
import org.bouncycastle.cert.X509CertificateHolder
import zio.{Tag => _, _}
Expand Down Expand Up @@ -421,6 +421,13 @@ final case class RestExtractorService (
extractOneValue(params, "prettify")(toBoolean).map(_.getOrElse(false)).getOrElse(false)
}

def extractSecret(req: Req): Box[Secret] = {
req.json match {
case Full(json) => extractSecretFromJson(json)
case _ => extractSecretFromJson(req.params)
}
}

def extractReason (req : Req) : Box[Option[String]] = {
import ReasonBehavior._
userPropertyService.reasonsFieldBehavior match {
Expand Down Expand Up @@ -1302,4 +1309,16 @@ final case class RestExtractorService (
}

}

def extractSecretFromJson(json: JValue): Box[Secret] = {
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))
}
} yield s
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +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 :: Nil
SystemApi.GetParametersZipArchive.x :: SystemApi.GetHealthcheckResult.x :: SecretVaultApi.GetSecrets.x ::
SecretVaultApi.AddSecret.x :: SecretVaultApi.DeleteSecret.x :: SecretVaultApi.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
@@ -0,0 +1,176 @@
/*
*************************************************************************************
* Copyright 2021 Normation SAS
*************************************************************************************
*
* This file is part of Rudder.
*
* Rudder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In accordance with the terms of section 7 (7. Additional Terms.) of
* the GNU General Public License version 3, the copyright holders add
* the following Additional permissions:
* Notwithstanding to the terms of section 5 (5. Conveying Modified Source
* Versions) and 6 (6. Conveying Non-Source Forms.) of the GNU General
* Public License version 3, when you create a Related Module, this
* Related Module is not considered as a part of the work and may be
* distributed under the license agreement of your choice.
* A "Related Module" means a set of sources files including their
* documentation that, without modification of the Source Code, enables
* supplementary functions or services in addition to those offered by
* the Software.
*
* Rudder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Rudder. If not, see <http://www.gnu.org/licenses/>.
*
*************************************************************************************
*/
package com.normation.rudder.rest.lift

import com.normation.box._
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.web.services.Secret
import com.normation.rudder.web.services.SecretVaultService
import net.liftweb.common._
import net.liftweb.http.LiftResponse
import net.liftweb.http.Req
import net.liftweb.json.JArray
import net.liftweb.json.JsonDSL._

class SecretVaultApi(
restExtractorService : RestExtractorService
, secretVaultService : SecretVaultService
) extends LiftApiModuleProvider[API] {

def schemas = API

def serializeSecret(secret : Secret) = {
( ("name" -> secret.name)
~ ("value" -> secret.value)
)
}

def getLiftEndpoints(): List[LiftApiModule] = {
API.endpoints.map(
e => e match {
case API.GetSecrets => GetSecrets
case API.AddSecret => AddSecret
case API.UpdateSecret => UpdateSecret
case API.DeleteSecret => DeleteSecret

}
)
}

object GetSecrets extends LiftApiModule0 {
val schema = API.GetSecrets
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

val res = for {
secrets <- secretVaultService.getSecrets
} yield {
secrets.map(serializeSecret)
}

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)
}
}
}

object AddSecret extends LiftApiModule0 {
val schema = API.AddSecret
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

val res = for {
secret <- restExtractorService.extractSecret(req)
_ <- secretVaultService.addSecret(secret).toBox
} yield {
serializeSecret(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)
}
}
}


object DeleteSecret extends LiftApiModule {
val schema = API.DeleteSecret
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 {
_ <- secretVaultService.deleteSecret(id).toBox
} yield {
id
}
res match {
case Full(secretId) =>
RestUtils.toJsonResponse(None, id)
case eb: EmptyBox =>
val message = (eb ?~ s"Error when trying delete a secret entry").messageChain
RestUtils.toJsonError(None, message)(action, true)
}
}
}

object UpdateSecret extends LiftApiModule0 {
val schema = API.UpdateSecret
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

val res = for {
secret <- restExtractorService.extractSecret(req)
_ <- secretVaultService.updateSecret(secret).toBox
} yield {
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)
}
}
}

}
Loading

0 comments on commit 4443cf0

Please sign in to comment.