mirror of
https://github.com/signalapp/Signal-Server.git
synced 2024-09-20 03:52:16 +02:00
Use APNs signing keys instead of expiring certificates.
This commit is contained in:
parent
001a9310c3
commit
b1d11d4f69
@ -82,9 +82,11 @@ database: # Postgresql database configuration
|
|||||||
url:
|
url:
|
||||||
|
|
||||||
apn: # Apple Push Notifications configuration
|
apn: # Apple Push Notifications configuration
|
||||||
|
sandbox: true
|
||||||
bundleId:
|
bundleId:
|
||||||
pushCertificate:
|
keyId:
|
||||||
pushKey:
|
teamId:
|
||||||
|
signingKey:
|
||||||
|
|
||||||
gcm: # GCM Configuration
|
gcm: # GCM Configuration
|
||||||
senderId:
|
senderId:
|
||||||
|
@ -24,11 +24,15 @@ public class ApnConfiguration {
|
|||||||
|
|
||||||
@NotEmpty
|
@NotEmpty
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private String pushCertificate;
|
private String teamId;
|
||||||
|
|
||||||
@NotEmpty
|
@NotEmpty
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private String pushKey;
|
private String keyId;
|
||||||
|
|
||||||
|
@NotEmpty
|
||||||
|
@JsonProperty
|
||||||
|
private String signingKey;
|
||||||
|
|
||||||
@NotEmpty
|
@NotEmpty
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
@ -37,12 +41,16 @@ public class ApnConfiguration {
|
|||||||
@JsonProperty
|
@JsonProperty
|
||||||
private boolean sandbox = false;
|
private boolean sandbox = false;
|
||||||
|
|
||||||
public String getPushCertificate() {
|
public String getTeamId() {
|
||||||
return pushCertificate;
|
return teamId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPushKey() {
|
public String getKeyId() {
|
||||||
return pushKey;
|
return keyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSigningKey() {
|
||||||
|
return signingKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBundleId() {
|
public String getBundleId() {
|
||||||
|
@ -35,6 +35,8 @@ import org.whispersystems.textsecuregcm.util.Constants;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@ -61,13 +63,14 @@ public class APNSender implements Managed {
|
|||||||
private final RetryingApnsClient apnsClient;
|
private final RetryingApnsClient apnsClient;
|
||||||
|
|
||||||
public APNSender(AccountsManager accountsManager, ApnConfiguration configuration)
|
public APNSender(AccountsManager accountsManager, ApnConfiguration configuration)
|
||||||
throws IOException
|
throws IOException, NoSuchAlgorithmException, InvalidKeyException
|
||||||
{
|
{
|
||||||
this.accountsManager = accountsManager;
|
this.accountsManager = accountsManager;
|
||||||
this.bundleId = configuration.getBundleId();
|
this.bundleId = configuration.getBundleId();
|
||||||
this.sandbox = configuration.isSandboxEnabled();
|
this.sandbox = configuration.isSandboxEnabled();
|
||||||
this.apnsClient = new RetryingApnsClient(configuration.getPushCertificate(),
|
this.apnsClient = new RetryingApnsClient(configuration.getSigningKey(),
|
||||||
configuration.getPushKey(),
|
configuration.getTeamId(),
|
||||||
|
configuration.getKeyId(),
|
||||||
sandbox);
|
sandbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,28 +7,26 @@ import com.eatthepath.pushy.apns.ApnsClient;
|
|||||||
import com.eatthepath.pushy.apns.ApnsClientBuilder;
|
import com.eatthepath.pushy.apns.ApnsClientBuilder;
|
||||||
import com.eatthepath.pushy.apns.DeliveryPriority;
|
import com.eatthepath.pushy.apns.DeliveryPriority;
|
||||||
import com.eatthepath.pushy.apns.PushNotificationResponse;
|
import com.eatthepath.pushy.apns.PushNotificationResponse;
|
||||||
|
import com.eatthepath.pushy.apns.auth.ApnsSigningKey;
|
||||||
import com.eatthepath.pushy.apns.metrics.dropwizard.DropwizardApnsClientMetricsListener;
|
import com.eatthepath.pushy.apns.metrics.dropwizard.DropwizardApnsClientMetricsListener;
|
||||||
import com.eatthepath.pushy.apns.util.SimpleApnsPushNotification;
|
import com.eatthepath.pushy.apns.util.SimpleApnsPushNotification;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
import org.bouncycastle.openssl.PEMReader;
|
import io.netty.util.concurrent.GenericFutureListener;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.textsecuregcm.util.Constants;
|
import org.whispersystems.textsecuregcm.util.Constants;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.KeyPair;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import static com.codahale.metrics.MetricRegistry.name;
|
import static com.codahale.metrics.MetricRegistry.name;
|
||||||
import io.netty.util.concurrent.GenericFutureListener;
|
|
||||||
|
|
||||||
public class RetryingApnsClient {
|
public class RetryingApnsClient {
|
||||||
|
|
||||||
@ -36,8 +34,8 @@ public class RetryingApnsClient {
|
|||||||
|
|
||||||
private final ApnsClient apnsClient;
|
private final ApnsClient apnsClient;
|
||||||
|
|
||||||
RetryingApnsClient(String apnCertificate, String apnKey, boolean sandbox)
|
RetryingApnsClient(String apnSigningKey, String teamId, String keyId, boolean sandbox)
|
||||||
throws IOException
|
throws IOException, InvalidKeyException, NoSuchAlgorithmException
|
||||||
{
|
{
|
||||||
MetricRegistry metricRegistry = SharedMetricRegistries.getOrCreate(Constants.METRICS_NAME);
|
MetricRegistry metricRegistry = SharedMetricRegistries.getOrCreate(Constants.METRICS_NAME);
|
||||||
DropwizardApnsClientMetricsListener metricsListener = new DropwizardApnsClientMetricsListener();
|
DropwizardApnsClientMetricsListener metricsListener = new DropwizardApnsClientMetricsListener();
|
||||||
@ -46,8 +44,7 @@ public class RetryingApnsClient {
|
|||||||
metricRegistry.register(name(getClass(), entry.getKey()), entry.getValue());
|
metricRegistry.register(name(getClass(), entry.getKey()), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.apnsClient = new ApnsClientBuilder().setClientCredentials(initializeCertificate(apnCertificate),
|
this.apnsClient = new ApnsClientBuilder().setSigningKey(ApnsSigningKey.loadFromInputStream(new ByteArrayInputStream(apnSigningKey.getBytes()), teamId, keyId))
|
||||||
initializePrivateKey(apnKey), null)
|
|
||||||
.setMetricsListener(metricsListener)
|
.setMetricsListener(metricsListener)
|
||||||
.setApnsServer(sandbox ? ApnsClientBuilder.DEVELOPMENT_APNS_HOST : ApnsClientBuilder.PRODUCTION_APNS_HOST)
|
.setApnsServer(sandbox ? ApnsClientBuilder.DEVELOPMENT_APNS_HOST : ApnsClientBuilder.PRODUCTION_APNS_HOST)
|
||||||
.build();
|
.build();
|
||||||
@ -71,16 +68,6 @@ public class RetryingApnsClient {
|
|||||||
apnsClient.close();
|
apnsClient.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static X509Certificate initializeCertificate(String pemCertificate) throws IOException {
|
|
||||||
PEMReader reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(pemCertificate.getBytes())));
|
|
||||||
return (X509Certificate) reader.readObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static PrivateKey initializePrivateKey(String pemKey) throws IOException {
|
|
||||||
PEMReader reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(pemKey.getBytes())));
|
|
||||||
return ((KeyPair) reader.readObject()).getPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ResponseHandler implements GenericFutureListener<io.netty.util.concurrent.Future<PushNotificationResponse<SimpleApnsPushNotification>>> {
|
private static final class ResponseHandler implements GenericFutureListener<io.netty.util.concurrent.Future<PushNotificationResponse<SimpleApnsPushNotification>>> {
|
||||||
|
|
||||||
private final SettableFuture<ApnResult> future;
|
private final SettableFuture<ApnResult> future;
|
||||||
|
Loading…
Reference in New Issue
Block a user