mirror of https://github.com/MISP/misp-bump
commit
9d1349d38f
13
README.md
13
README.md
|
@ -4,13 +4,12 @@ Simple and secure synchronisation of MISP instances
|
||||||
# What is MISPbump?
|
# What is MISPbump?
|
||||||
With MISPbump admins can easily synchronize MISP instances by exchanging relevant information via encrypted QR codes.
|
With MISPbump admins can easily synchronize MISP instances by exchanging relevant information via encrypted QR codes.
|
||||||
|
|
||||||
Note: only **use case 1** from the [documentation](https://www.circl.lu/doc/misp/sharing/) is supported.
|
> Note that only **use case 1** from the [documentation](https://www.circl.lu/doc/misp/sharing/) is supported.
|
||||||
|
|
||||||
# How does MISPbump work?
|
# How does MISPbump work?
|
||||||
First of all: MISP admins login by providing the base URL of their instance and their authkey (automationkey).
|
MISP admins log in by providing the **base URL** of their instance and their **authkey**.
|
||||||
|
|
||||||
On a successfull login the admins profile and the linked organisation information will be downloaded automatically.
|
After a successfull login the admin's profile and the linked organisation information will be downloaded.
|
||||||
This information can be updated at any time in the profile screen.
|
|
||||||
|
|
||||||
In the main screen you can start a synchronisation process by pressing the dedicated button.
|
In the main screen you can start a synchronisation process by pressing the dedicated button.
|
||||||
|
|
||||||
|
@ -26,11 +25,11 @@ The synchronisation process consists of 3 steps:
|
||||||
+ Own User: Email
|
+ Own User: Email
|
||||||
+ Own MISP instance: base URL
|
+ Own MISP instance: base URL
|
||||||
+ Generated: sync user authkey, sync user password
|
+ Generated: sync user authkey, sync user password
|
||||||
(your partner will create a sync user with these credentials)
|
(your partner will create a sync user with these credentials for you)
|
||||||
|
|
||||||
The synchronisation information is encrypted with AES using the shared secret (from step 1).
|
The synchronisation information is encrypted with AES using the shared secret (from step 1).
|
||||||
|
|
||||||
The sync process information will be saved securely on the device, that means the upload can be started any time in the future.
|
The synchronisation process information will be saved securely on the device.
|
||||||
|
|
||||||
|
|
||||||
1. **Upload information to own MISP instance**
|
1. **Upload information to own MISP instance**
|
||||||
|
@ -41,7 +40,7 @@ The synchronisation process consists of 3 steps:
|
||||||
1. Create sync user & add to organisation
|
1. Create sync user & add to organisation
|
||||||
1. Create sync server & populate with information above
|
1. Create sync server & populate with information above
|
||||||
|
|
||||||
After that the two MISP instances are connected.
|
After that the two MISP instances are able to share Events based on their permissions.
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
+ [Retrofit](https://github.com/square/retrofit)
|
+ [Retrofit](https://github.com/square/retrofit)
|
||||||
|
|
|
@ -57,7 +57,8 @@
|
||||||
android:layout_margin="16dp"
|
android:layout_margin="16dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:contentDescription="@string/content_description_sync_status_icon" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:background="@color/black_10"
|
android:background="@color/black_10"
|
||||||
|
|
|
@ -58,4 +58,5 @@
|
||||||
<string name="upload_changes">Upload Changes</string>
|
<string name="upload_changes">Upload Changes</string>
|
||||||
<string name="download_changes">Download Changes</string>
|
<string name="download_changes">Download Changes</string>
|
||||||
<string name="label_delete_sync">Delete Synchronisation</string>
|
<string name="label_delete_sync">Delete Synchronisation</string>
|
||||||
|
<string name="content_description_sync_status_icon">Shows if local changes are already uploaded to MISP instance</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
/build
|
|
|
@ -1,34 +0,0 @@
|
||||||
apply plugin: 'com.android.library'
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion 29
|
|
||||||
buildToolsVersion "29.0.1"
|
|
||||||
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
minSdkVersion 21
|
|
||||||
targetSdkVersion 29
|
|
||||||
versionCode 1
|
|
||||||
versionName "1.0"
|
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled false
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
|
||||||
testImplementation 'junit:junit:4.12'
|
|
||||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
# Add project specific ProGuard rules here.
|
|
||||||
# You can control the set of applied configuration files using the
|
|
||||||
# proguardFiles setting in build.gradle.
|
|
||||||
#
|
|
||||||
# For more details, see
|
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following
|
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
|
||||||
# class:
|
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
||||||
# public *;
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Uncomment this to preserve the line number information for
|
|
||||||
# debugging stack traces.
|
|
||||||
#-keepattributes SourceFile,LineNumberTable
|
|
||||||
|
|
||||||
# If you keep the line number information, uncomment this to
|
|
||||||
# hide the original source file name.
|
|
||||||
#-renamesourcefileattribute SourceFile
|
|
|
@ -1,29 +0,0 @@
|
||||||
package lu.circl.expandablecardview;
|
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
public void useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
|
||||||
|
|
||||||
assertEquals("lu.circl.expandablecardview.test", appContext.getPackageName());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
<manifest package="lu.circl.expandablecardview" />
|
|
|
@ -1,177 +0,0 @@
|
||||||
package lu.circl.expandablecardview;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.TypedArray;
|
|
||||||
import android.graphics.drawable.GradientDrawable;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.animation.Animation;
|
|
||||||
import android.view.animation.Transformation;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
|
|
||||||
public class ExpandableCardView extends LinearLayout {
|
|
||||||
|
|
||||||
private Context context;
|
|
||||||
|
|
||||||
private FrameLayout contentLayout;
|
|
||||||
private int cardContentPadding;
|
|
||||||
|
|
||||||
private boolean isExpanded = true;
|
|
||||||
private int animationSpeed = 200;
|
|
||||||
|
|
||||||
|
|
||||||
public ExpandableCardView(Context context) {
|
|
||||||
this(context, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpandableCardView(Context context, AttributeSet attrs) {
|
|
||||||
this(context, attrs, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpandableCardView(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
||||||
super(context, attrs, defStyleAttr);
|
|
||||||
this.context = context;
|
|
||||||
|
|
||||||
setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
|
||||||
setOrientation(VERTICAL);
|
|
||||||
setClipToOutline(true);
|
|
||||||
|
|
||||||
TypedArray customAttributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ExpandableCardView, defStyleAttr, 0);
|
|
||||||
|
|
||||||
// general
|
|
||||||
int cornerRadius = customAttributes.getDimensionPixelSize(R.styleable.ExpandableCardView_card_corner_radius, 12);
|
|
||||||
|
|
||||||
// header
|
|
||||||
String cardTitle = customAttributes.getString(R.styleable.ExpandableCardView_card_title);
|
|
||||||
int iconRes = customAttributes.getResourceId(R.styleable.ExpandableCardView_card_icon, 0x0);
|
|
||||||
int headerForegroundColor = customAttributes.getColor(R.styleable.ExpandableCardView_card_header_foreground_color, 0xFF000000);
|
|
||||||
int headerBackgroundColor = customAttributes.getColor(R.styleable.ExpandableCardView_card_header_background_color, 0xFFFFFFFF);
|
|
||||||
|
|
||||||
// content
|
|
||||||
cardContentPadding = customAttributes.getDimensionPixelSize(R.styleable.ExpandableCardView_card_content_padding, 0);
|
|
||||||
int cardContentBackgroundColor = customAttributes.getColor(R.styleable.ExpandableCardView_card_content_background_color, 0xFFFFFFFF);
|
|
||||||
|
|
||||||
customAttributes.recycle();
|
|
||||||
|
|
||||||
GradientDrawable cardBackground = new GradientDrawable();
|
|
||||||
cardBackground.setCornerRadius(cornerRadius);
|
|
||||||
cardBackground.setColor(cardContentBackgroundColor);
|
|
||||||
|
|
||||||
setBackground(cardBackground);
|
|
||||||
setElevation(10);
|
|
||||||
|
|
||||||
initHeader(cardTitle, iconRes, headerBackgroundColor, headerForegroundColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addView(View child, int index, ViewGroup.LayoutParams params) {
|
|
||||||
if (getChildCount() == 0) {
|
|
||||||
super.addView(child, index, params); // add header
|
|
||||||
} else {
|
|
||||||
if (contentLayout == null) {
|
|
||||||
contentLayout = new FrameLayout(context);
|
|
||||||
contentLayout.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
|
||||||
contentLayout.setPadding(cardContentPadding, cardContentPadding, cardContentPadding, cardContentPadding);
|
|
||||||
|
|
||||||
super.addView(contentLayout, index, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
|
||||||
}
|
|
||||||
|
|
||||||
contentLayout.addView(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void initHeader(String title, int iconRes, int backgroundColor, int foregroundColor) {
|
|
||||||
View header = LayoutInflater.from(context).inflate(R.layout.expandable_card_view_header, this, true);
|
|
||||||
LinearLayout ll = header.findViewById(R.id.llRoot);
|
|
||||||
ll.setBackgroundColor(backgroundColor);
|
|
||||||
|
|
||||||
TextView titleTextView = header.findViewById(R.id.expandable_card_view_header_title);
|
|
||||||
titleTextView.setText(title);
|
|
||||||
titleTextView.setTextColor(foregroundColor);
|
|
||||||
|
|
||||||
ImageView iconView = header.findViewById(R.id.expandable_card_view_header_icon);
|
|
||||||
if (iconRes == 0x0) {
|
|
||||||
iconView.setVisibility(GONE);
|
|
||||||
} else {
|
|
||||||
iconView.setImageResource(iconRes);
|
|
||||||
iconView.setColorFilter(foregroundColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
final ImageButton expandToggle = header.findViewById(R.id.expandable_card_view_header_toggle);
|
|
||||||
expandToggle.setColorFilter(foregroundColor);
|
|
||||||
expandToggle.setOnClickListener(new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
if (isExpanded) {
|
|
||||||
collapse(contentLayout);
|
|
||||||
expandToggle.animate().rotation(0).setDuration(animationSpeed);
|
|
||||||
} else {
|
|
||||||
expand(contentLayout);
|
|
||||||
expandToggle.animate().rotation(180).setDuration(animationSpeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
isExpanded = !isExpanded;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expand(final View v) {
|
|
||||||
int matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec(((View) v.getParent()).getWidth(), View.MeasureSpec.EXACTLY);
|
|
||||||
int wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
|
||||||
v.measure(matchParentMeasureSpec, wrapContentMeasureSpec);
|
|
||||||
final int targetHeight = v.getMeasuredHeight();
|
|
||||||
|
|
||||||
v.getLayoutParams().height = 1;
|
|
||||||
v.setVisibility(View.VISIBLE);
|
|
||||||
Animation a = new Animation() {
|
|
||||||
@Override
|
|
||||||
protected void applyTransformation(float interpolatedTime, Transformation t) {
|
|
||||||
v.getLayoutParams().height = interpolatedTime == 1
|
|
||||||
? LayoutParams.WRAP_CONTENT
|
|
||||||
: (int) (targetHeight * interpolatedTime);
|
|
||||||
v.requestLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean willChangeBounds() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
a.setDuration(animationSpeed);
|
|
||||||
v.startAnimation(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void collapse(final View v) {
|
|
||||||
final int initialHeight = v.getMeasuredHeight();
|
|
||||||
|
|
||||||
Animation a = new Animation() {
|
|
||||||
@Override
|
|
||||||
protected void applyTransformation(float interpolatedTime, Transformation t) {
|
|
||||||
if (interpolatedTime == 1) {
|
|
||||||
v.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
v.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
|
|
||||||
v.requestLayout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean willChangeBounds() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
a.setDuration(animationSpeed);
|
|
||||||
v.startAnimation(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
|
|
||||||
</vector>
|
|
|
@ -1,9 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M7.41,7.84L12,12.42l4.59,-4.58L18,9.25l-6,6 -6,-6z"/>
|
|
||||||
</vector>
|
|
|
@ -1,37 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/llRoot"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/expandable_card_view_header_icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
tools:src="@drawable/ic_info_outline"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/expandable_card_view_header_title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
tools:text="Card Title"/>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/expandable_card_view_header_toggle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/ic_keyboard_arrow_down"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
|
@ -1,17 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<declare-styleable name="ExpandableCardView">
|
|
||||||
// general
|
|
||||||
<attr name="card_corner_radius" format="dimension"/>
|
|
||||||
|
|
||||||
// header
|
|
||||||
<attr name="card_title" format="string"/>
|
|
||||||
<attr name="card_icon" format="reference"/>
|
|
||||||
<attr name="card_header_background_color" format="color"/>
|
|
||||||
<attr name="card_header_foreground_color" format="color"/>
|
|
||||||
|
|
||||||
// content
|
|
||||||
<attr name="card_content_padding" format="dimension"/>
|
|
||||||
<attr name="card_content_background_color" format="color"/>
|
|
||||||
</declare-styleable>
|
|
||||||
</resources>
|
|
|
@ -1,3 +0,0 @@
|
||||||
<resources>
|
|
||||||
<string name="app_name">ExpandableCardView</string>
|
|
||||||
</resources>
|
|
|
@ -1,19 +0,0 @@
|
||||||
package lu.circl.expandablecardview;
|
|
||||||
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
|
||||||
*
|
|
||||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
|
||||||
*/
|
|
||||||
public class ExampleUnitTest {
|
|
||||||
@Test
|
|
||||||
public void addition_isCorrect() {
|
|
||||||
assertEquals(4, 2 + 2);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue