Skip to content

Commit

Permalink
TFP-5952 flytt auditlogging til PEP (#1414)
Browse files Browse the repository at this point in the history
* TFP-5952 flytt auditlogging til PEP

* Flytte attributtnavn til logger
  • Loading branch information
jolarsen authored Feb 9, 2025
1 parent c346fe3 commit 0932ad0
Show file tree
Hide file tree
Showing 10 changed files with 356 additions and 216 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,19 @@
import jakarta.enterprise.context.Dependent;
import jakarta.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import no.nav.vedtak.log.audit.Auditdata;
import no.nav.vedtak.log.audit.AuditdataHeader;
import no.nav.vedtak.log.audit.Auditlogger;
import no.nav.vedtak.log.audit.CefField;
import no.nav.vedtak.log.audit.EventClassId;
import no.nav.vedtak.sikkerhet.abac.beskyttet.ActionType;
import no.nav.vedtak.sikkerhet.abac.beskyttet.ResourceType;
import no.nav.vedtak.sikkerhet.abac.internal.BeskyttetRessursAttributter;
import no.nav.vedtak.sikkerhet.abac.pdp.AppRessursData;
import no.nav.vedtak.sikkerhet.kontekst.IdentType;

/**
* Dette loggformatet er avklart med Arcsight. Eventuelle nye felter skal
Expand All @@ -43,34 +49,39 @@
@Dependent
public class AbacAuditlogger {

private static final Logger LOG = LoggerFactory.getLogger(AbacAuditlogger.class);

private final Auditlogger auditlogger;

@Inject
public AbacAuditlogger(Auditlogger auditlogger) {
this.auditlogger = auditlogger;
}

public void loggTilgang(String userId, Tilgangsbeslutning tilgangsbeslutning) {
logg(userId, tilgangsbeslutning, Access.GRANTED);
}

public void loggDeny(String userId, Tilgangsbeslutning tilgangsbeslutning) {
logg(userId, tilgangsbeslutning, Access.DENIED);
}
public void loggUtfall(AbacResultat utfall, BeskyttetRessursAttributter beskyttetRessursAttributter, AppRessursData appRessursData) {
if (IdentType.Systemressurs.equals(beskyttetRessursAttributter.getIdentType())) {
// Skal ikke auditlogge systemkall
if (!utfall.fikkTilgang()) {
LOG.info("ABAC AVSLAG SYSTEMBRUKER {} tjeneste {}", beskyttetRessursAttributter.getBrukerId(), beskyttetRessursAttributter.getServicePath());
}
} else if (beskyttetRessursAttributter.isSporingslogg()) {
try {
logg(beskyttetRessursAttributter, appRessursData, utfall.fikkTilgang() ? Access.GRANTED : Access.DENIED);
} catch (Exception e) {
LOG.warn("ABAC AUDITLOG FAILURE ident {} tjeneste {}", beskyttetRessursAttributter.getIdentType(), beskyttetRessursAttributter.getServicePath(), e);
}

private void logg(String userId, Tilgangsbeslutning tilgangsbeslutning, Access access) {
logg(userId, tilgangsbeslutning.beskyttetRessursAttributter(), tilgangsbeslutning.appRessursData(), access);
}
}

private void logg(String userId, BeskyttetRessursAttributter beskyttetRessursAttributter, AppRessursData appRessursData, Access access) {
private void logg(BeskyttetRessursAttributter beskyttetRessursAttributter, AppRessursData appRessursData, Access access) {
requireNonNull(beskyttetRessursAttributter);
requireNonNull(beskyttetRessursAttributter.getDataAttributter());

String abacAction = requireNonNull(beskyttetRessursAttributter.getActionType().getEksternKode());
var header = createHeader(abacAction, access);
var fields = createDefaultAbacFields(userId, beskyttetRessursAttributter);
var header = createHeader(beskyttetRessursAttributter.getActionType(), access);
var fields = createDefaultAbacFields(beskyttetRessursAttributter);

List<String> ids = getBerortBrukerId(appRessursData);
List<String> ids = getBerortBrukerId(appRessursData); // TODO: Vurder å kun logge for hovedperson
for (String aktorId : ids) {
loggTilgangPerBerortAktoer(header, fields, aktorId);
}
Expand All @@ -83,7 +94,7 @@ private void loggTilgangPerBerortAktoer(AuditdataHeader header, Set<CefField> fi
auditlogger.logg(auditdata);
}

private AuditdataHeader createHeader(String abacAction, Access access) {
private AuditdataHeader createHeader(ActionType abacAction, Access access) {
return new AuditdataHeader.Builder().medVendor(auditlogger.getDefaultVendor())
.medProduct(auditlogger.getDefaultProduct())
.medEventClassId(finnEventClassIdFra(abacAction))
Expand All @@ -92,18 +103,18 @@ private AuditdataHeader createHeader(String abacAction, Access access) {
.build();
}

private Set<CefField> createDefaultAbacFields(String userId, BeskyttetRessursAttributter beskyttetRessursAttributter) {
var abacAction = requireNonNull(beskyttetRessursAttributter.getActionType().getEksternKode());
var abacResourceType = requireNonNull(beskyttetRessursAttributter.getResourceType());
protected Set<CefField> createDefaultAbacFields(BeskyttetRessursAttributter beskyttetRessursAttributter) {
var abacAction = requireNonNull(mapActionType(beskyttetRessursAttributter.getActionType()));
var abacResourceType = requireNonNull(mapResourceType(beskyttetRessursAttributter.getResourceType()));

Set<CefField> fields = new HashSet<>();
fields.add(new CefField(EVENT_TIME, System.currentTimeMillis()));
fields.add(new CefField(REQUEST, beskyttetRessursAttributter.getServicePath()));
fields.add(new CefField(ABAC_RESOURCE_TYPE, abacResourceType.getResourceTypeAttribute()));
fields.add(new CefField(ABAC_RESOURCE_TYPE, abacResourceType));
fields.add(new CefField(ABAC_ACTION, abacAction));

if (userId != null) {
fields.add(new CefField(USER_ID, userId));
if (beskyttetRessursAttributter.getBrukerId() != null) {
fields.add(new CefField(USER_ID, beskyttetRessursAttributter.getBrukerId()));
}

getOneOfNew(beskyttetRessursAttributter.getDataAttributter(), SAKSNUMMER, FAGSAK_ID).ifPresent(fagsak -> fields.addAll(forSaksnummer(fagsak)));
Expand Down Expand Up @@ -136,15 +147,33 @@ private static Optional<String> getOneOfNew(AbacDataAttributter attributter, Aba
return Optional.empty();
}

private static EventClassId finnEventClassIdFra(String abacAction) {
private static EventClassId finnEventClassIdFra(ActionType abacAction) {
return switch (abacAction) {
case "read" -> AUDIT_ACCESS; /* Fall-through */
case "delete", "update" -> AUDIT_UPDATE;
case "create" -> AUDIT_CREATE;
case READ -> AUDIT_ACCESS; /* Fall-through */
case DELETE, UPDATE -> AUDIT_UPDATE;
case CREATE -> AUDIT_CREATE;
default -> throw new IllegalArgumentException("Ukjent abacAction: " + abacAction);
};
}

private static String mapActionType(ActionType actionType) {
return actionType == ActionType.DUMMY ? null : actionType.name().toLowerCase();
}

// TODO: vurder å forkorte vekk abac.attributter.
private static String mapResourceType(ResourceType resourceType) {
return switch (resourceType) {
case APPLIKASJON -> "no.nav.abac.attributter.foreldrepenger";
case DRIFT -> "no.nav.abac.attributter.foreldrepenger.drift";
case FAGSAK -> "no.nav.abac.attributter.foreldrepenger.fagsak";
case VENTEFRIST -> "no.nav.abac.attributter.foreldrepenger.fagsak.ventefrist";
case OPPGAVESTYRING_AVDELINGENHET -> "no.nav.abac.attributter.foreldrepenger.oppgavestyring.avdelingsenhet";
case OPPGAVESTYRING -> "no.nav.abac.attributter.foreldrepenger.oppgavestyring";
case UTTAKSPLAN -> "no.nav.abac.attributter.foreldrepenger.uttaksplan";
case PIP, DUMMY -> throw new IllegalArgumentException("Ulovlig resourceType: " + resourceType);
};
}

/**
* Standard hos NAV er at tilgang logges som "INFO" og avslag som "WARN". Merk
* at dette avviker fra CEF-standarden.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ public enum AbacResultat {
AVSLÅTT_KODE_6,
AVSLÅTT_EGEN_ANSATT,
AVSLÅTT_ANNEN_ÅRSAK;

public boolean fikkTilgang() {
return this == GODKJENT;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Optional;

import jakarta.annotation.Priority;
import jakarta.enterprise.context.Dependent;
Expand All @@ -13,84 +12,52 @@
import jakarta.interceptor.InvocationContext;

import org.jboss.weld.interceptor.util.proxy.TargetInstanceProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import no.nav.foreldrepenger.konfig.Environment;
import no.nav.vedtak.exception.TekniskException;
import no.nav.vedtak.sikkerhet.abac.beskyttet.ActionType;
import no.nav.vedtak.sikkerhet.abac.beskyttet.ResourceType;
import no.nav.vedtak.sikkerhet.abac.internal.ActionUthenter;
import no.nav.vedtak.sikkerhet.abac.internal.BeskyttetRessursAttributter;
import no.nav.vedtak.sikkerhet.kontekst.IdentType;

@BeskyttetRessurs(actionType = ActionType.DUMMY, resourceType = ResourceType.DUMMY)
@Interceptor
@Priority(Interceptor.Priority.APPLICATION + 11)
@Dependent
public class BeskyttetRessursInterceptor {

private static final Environment ENV = Environment.current();
private static final Logger LOG = LoggerFactory.getLogger(BeskyttetRessursInterceptor.class);

private final Pep pep;
private final AbacAuditlogger abacAuditlogger;
private final TokenProvider tokenProvider;

@Inject
public BeskyttetRessursInterceptor(Pep pep, AbacAuditlogger abacAuditlogger, TokenProvider provider) {
public BeskyttetRessursInterceptor(Pep pep, TokenProvider provider) {
this.pep = pep;
this.abacAuditlogger = abacAuditlogger;
this.tokenProvider = provider;
}

@AroundInvoke
public Object wrapTransaction(final InvocationContext invocationContext) throws Exception {
var dataAttributter = finnAbacDataAttributter(invocationContext);
var beskyttetRessursAttributter = hentBeskyttetRessursAttributter(invocationContext, dataAttributter);
var method = invocationContext.getMethod();
var dataAttributter = finnAbacDataAttributter(method, invocationContext.getParameters());
var beskyttetRessursAttributter = hentBeskyttetRessursAttributter(method, getOpprinneligKlasse(invocationContext), dataAttributter);

var beslutning = pep.vurderTilgang(beskyttetRessursAttributter);
if (beslutning.fikkTilgang()) {
return proceed(invocationContext, beslutning);
}
return ikkeTilgang(beslutning);
}

private Object proceed(InvocationContext invocationContext, Tilgangsbeslutning beslutning) throws Exception {
Method method = invocationContext.getMethod();
boolean sporingslogges = method.getAnnotation(BeskyttetRessurs.class).sporingslogg();
if (!erSystembrukerKall(beslutning.beskyttetRessursAttributter()) && sporingslogges) {
Object resultat = invocationContext.proceed();
abacAuditlogger.loggTilgang(tokenProvider.getUid(), beslutning);
return resultat;
}
return invocationContext.proceed();
}

private Object ikkeTilgang(Tilgangsbeslutning beslutning) {
if (!erSystembrukerKall(beslutning.beskyttetRessursAttributter())) {
abacAuditlogger.loggDeny(tokenProvider.getUid(), beslutning);
return invocationContext.proceed();
} else {
LOG.info("ABAC AVSLAG SYSTEMBRUKER {}", beslutning.beskyttetRessursAttributter().getBrukerId());
return ikkeTilgang(beslutning);
}
}

switch (beslutning.beslutningKode()) {
private Object ikkeTilgang(AbacResultat abacResultat) {
switch (abacResultat) {
case AVSLÅTT_KODE_6 -> throw new PepNektetTilgangException("F-709170", "Tilgangskontroll.Avslag.Kode6");
case AVSLÅTT_KODE_7 -> throw new PepNektetTilgangException("F-027901", "Tilgangskontroll.Avslag.Kode7");
case AVSLÅTT_EGEN_ANSATT -> throw new PepNektetTilgangException("F-788257", "Tilgangskontroll.Avslag.EgenAnsatt");
default -> throw new PepNektetTilgangException("F-608625", "Ikke tilgang");
}
}

private boolean erSystembrukerKall(BeskyttetRessursAttributter beskyttetRessursAttributter) {
return Optional.ofNullable(beskyttetRessursAttributter)
.map(BeskyttetRessursAttributter::getIdentType)
.filter(IdentType::erSystem)
.isPresent();
}

private BeskyttetRessursAttributter hentBeskyttetRessursAttributter(InvocationContext invocationContext, AbacDataAttributter dataAttributter) {
Class<?> clazz = getOpprinneligKlasse(invocationContext);
var method = invocationContext.getMethod();
private BeskyttetRessursAttributter hentBeskyttetRessursAttributter(Method method, Class<?> mClass, AbacDataAttributter dataAttributter) {
var beskyttetRessurs = method.getAnnotation(BeskyttetRessurs.class);

var token = Token.withOidcToken(tokenProvider.openIdToken());
Expand All @@ -104,19 +71,20 @@ private BeskyttetRessursAttributter hentBeskyttetRessursAttributter(InvocationCo
.medActionType(beskyttetRessurs.actionType())
.medAvailabilityType(beskyttetRessurs.availabilityType())
.medResourceType(finnResource(beskyttetRessurs))
.medSporingslogg(beskyttetRessurs.sporingslogg())
.medPepId(pep.pepId())
.medServicePath(utledAction(clazz, method))
.medServicePath(utledAction(mClass, method))
.medDataAttributter(dataAttributter)
.build();

}

static AbacDataAttributter finnAbacDataAttributter(InvocationContext invocationContext) {
var method = invocationContext.getMethod();
static AbacDataAttributter finnAbacDataAttributter(Method method, Object[] parameters) {
var dataAttributter = AbacDataAttributter.opprett();
var parameterDecl = method.getParameters();
for (int i = 0; i < method.getParameterCount(); i++) {
Object parameterValue = invocationContext.getParameters()[i];
var parameterCount = method.getParameterCount();
for (int i = 0; i < parameterCount; i++) {
Object parameterValue = parameters[i];
var tilpassetAnnotering = parameterDecl[i].getAnnotation(TilpassetAbacAttributt.class);
leggTilAttributterFraParameter(dataAttributter, parameterValue, tilpassetAnnotering);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

public interface Pep {

Tilgangsbeslutning vurderTilgang(BeskyttetRessursAttributter beskyttetRessursAttributter);
AbacResultat vurderTilgang(BeskyttetRessursAttributter beskyttetRessursAttributter);

default String pepId() {
return Environment.current().getNaisAppName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
import jakarta.enterprise.inject.Default;
import jakarta.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import no.nav.vedtak.sikkerhet.abac.beskyttet.ActionType;
import no.nav.vedtak.sikkerhet.abac.internal.BeskyttetRessursAttributter;
import no.nav.vedtak.sikkerhet.abac.pdp.AppRessursData;
Expand All @@ -30,8 +27,7 @@
@ApplicationScoped
public class PepImpl implements Pep {

private static final Logger LOG = LoggerFactory.getLogger(PepImpl.class);

private AbacAuditlogger abacAuditlogger;
private PopulasjonKlient populasjonKlient;
private AnsattGruppeKlient ansattGruppeKlient;
private PdpRequestBuilder pdpRequestBuilder;
Expand All @@ -42,21 +38,25 @@ public class PepImpl implements Pep {
}

@Inject
public PepImpl(PopulasjonKlient populasjonKlient, AnsattGruppeKlient ansattGruppeKlient, PdpRequestBuilder pdpRequestBuilder) {
public PepImpl(AbacAuditlogger abacAuditlogger,
PopulasjonKlient populasjonKlient,
AnsattGruppeKlient ansattGruppeKlient,
PdpRequestBuilder pdpRequestBuilder) {
this.abacAuditlogger = abacAuditlogger;
this.populasjonKlient = populasjonKlient;
this.ansattGruppeKlient = ansattGruppeKlient;
this.pdpRequestBuilder = pdpRequestBuilder;
}

@Override
public Tilgangsbeslutning vurderTilgang(BeskyttetRessursAttributter beskyttetRessursAttributter) {
public AbacResultat vurderTilgang(BeskyttetRessursAttributter beskyttetRessursAttributter) {
var appRessurser = pdpRequestBuilder.lagAppRessursData(beskyttetRessursAttributter.getDataAttributter());

var vurdering = forespørTilgang(beskyttetRessursAttributter, appRessurser);
return new Tilgangsbeslutning(vurdering.tilgangResultat(), beskyttetRessursAttributter, appRessurser);
abacAuditlogger.loggUtfall(vurdering.tilgangResultat(), beskyttetRessursAttributter, appRessurser);
return vurdering.tilgangResultat();
}


// Skal kunne kalles fra evt subklasser av PepImpl
protected Tilgangsvurdering forespørTilgang(BeskyttetRessursAttributter beskyttetRessursAttributter, AppRessursData appRessursData) {
if (ActionType.DUMMY.equals(beskyttetRessursAttributter.getActionType())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,4 @@
public record Tilgangsbeslutning(AbacResultat beslutningKode,
BeskyttetRessursAttributter beskyttetRessursAttributter,
AppRessursData appRessursData) {

public boolean fikkTilgang() {
return beslutningKode == AbacResultat.GODKJENT;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ public class BeskyttetRessursAttributter {
private String brukerId;
private UUID brukerOid;
private IdentType identType;
private Set<AnsattGruppe> ansattGrupper = new LinkedHashSet<>();
private final Set<AnsattGruppe> ansattGrupper = new LinkedHashSet<>();
private ActionType actionType;
private ResourceType resourceType;
private AvailabilityType availabilityType;
private Token token;
private String pepId;
private String servicePath;
private boolean sporingslogg = true;
private AbacDataAttributter dataAttributter;

public static Builder builder() {
Expand Down Expand Up @@ -60,6 +61,10 @@ public ResourceType getResourceType() {
return resourceType;
}

public boolean isSporingslogg() {
return sporingslogg;
}

public Token getToken() {
return token;
}
Expand Down Expand Up @@ -129,6 +134,11 @@ public Builder medResourceType(ResourceType resourceType) {
return this;
}

public Builder medSporingslogg(boolean sporingslogg) {
pdpRequest.sporingslogg = sporingslogg;
return this;
}

public Builder medPepId(String pepId) {
pdpRequest.pepId = pepId;
return this;
Expand Down
Loading

0 comments on commit 0932ad0

Please sign in to comment.