001/*
002 * acme4j - Java ACME client
003 *
004 * Copyright (C) 2016 Richard "Shred" Körber
005 *   http://acme4j.shredzone.org
006 *
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
013 */
014package org.shredzone.acme4j;
015
016import static java.util.stream.Collectors.toList;
017
018import java.net.URI;
019import java.net.URL;
020import java.time.Duration;
021import java.util.Collection;
022import java.util.Optional;
023
024import edu.umd.cs.findbugs.annotations.Nullable;
025import org.shredzone.acme4j.toolbox.JSON;
026import org.shredzone.acme4j.toolbox.JSON.Value;
027
028/**
029 * Contains metadata related to the provider.
030 */
031public class Metadata {
032
033    private final JSON meta;
034
035    /**
036     * Creates a new {@link Metadata} instance.
037     *
038     * @param meta
039     *            JSON map of metadata
040     */
041    public Metadata(JSON meta) {
042        this.meta = meta;
043    }
044
045    /**
046     * Returns an {@link URI} to the current terms of service, or {@code null} if not
047     * available.
048     */
049    @Nullable
050    public URI getTermsOfService() {
051        return meta.get("termsOfService").map(Value::asURI).orElse(null);
052    }
053
054    /**
055     * Returns an {@link URL} to a website providing more information about the ACME
056     * server. {@code null} if not available.
057     */
058    @Nullable
059    public URL getWebsite() {
060        return meta.get("website").map(Value::asURL).orElse(null);
061    }
062
063    /**
064     * Returns a collection of hostnames, which the ACME server recognises as referring to
065     * itself for the purposes of CAA record validation. Empty if not available.
066     */
067    public Collection<String> getCaaIdentities() {
068        return meta.get("caaIdentities")
069                .asArray()
070                .stream()
071                .map(Value::asString)
072                .collect(toList());
073    }
074
075    /**
076     * Returns whether an external account is required by this CA.
077     */
078    public boolean isExternalAccountRequired() {
079        return meta.get("externalAccountRequired").map(Value::asBoolean).orElse(false);
080    }
081
082    /**
083     * Returns whether the CA supports short-term auto renewal of certificates.
084     *
085     * @since 2.3
086     */
087    public boolean isAutoRenewalEnabled() {
088        return meta.get("auto-renewal").isPresent();
089    }
090
091    /**
092     * Returns the minimum acceptable value for the maximum validity of a certificate
093     * before auto renewal. {@code null} if the CA does not support short-term auto
094     * renewal.
095     *
096     * @since 2.3
097     */
098    @Nullable
099    public Duration getAutoRenewalMinLifetime() {
100        Optional<JSON> ar = meta.get("auto-renewal").optional().map(Value::asObject);
101        if (!ar.isPresent()) {
102            return null;
103        }
104        return ar.get().get("min-lifetime").map(Value::asDuration).orElse(null);
105    }
106
107    /**
108     * Returns the maximum delta between auto-renewal end date and auto-renewal start
109     * date. {@code null} if the CA does not support short-term auto renewal.
110     *
111     * @since 2.3
112     */
113    @Nullable
114    public Duration getAutoRenewalMaxDuration() {
115        Optional<JSON> ar = meta.get("auto-renewal").optional().map(Value::asObject);
116        if (!ar.isPresent()) {
117            return null;
118        }
119        return ar.get().get("max-duration").map(Value::asDuration).orElse(null);
120    }
121
122    /**
123     * Returns whether the CA also allows to fetch STAR certificates via GET request.
124     *
125     * @since 2.6
126     */
127    public boolean isAutoRenewalGetAllowed() {
128        Optional<JSON> ar = meta.get("auto-renewal").optional().map(Value::asObject);
129        if (!ar.isPresent()) {
130            return false;
131        }
132        return ar.get().get("allow-certificate-get").map(Value::asBoolean).orElse(false);
133    }
134
135    /**
136     * Returns the JSON representation of the metadata. This is useful for reading
137     * proprietary metadata properties.
138     */
139    public JSON getJSON() {
140        return meta;
141    }
142
143}